全面理解JavaScript中class的实现原理
一、class类概念与语法
ES5之前不存在类的概念,创建对象使用的构造函数,通过new操作符来创建;
为使JS更像面向对象,ES6版本引入class概念,其基本语法:
class Cat{ constructor(name,age){ this.name = name; this.age = age; } Say(){ return '我的名字是' + this.name; } } var cat1 = new Cat('有鱼',2); console.log(cat1.Say());//我的名字是有鱼
代码解析:
① constructor是一个构造函数方法,创建对象时自动调用该方法
② constructor是默认存在的,可以省略,程序亦可以调用
③ this指的是实例化对象
④类中声明的方法不能加function关键字
⑤方法之间不要用逗号分隔,否则会报错
二、class类与原型的关系
class类本质上就是一个函数,自身指向的就是构造函数,看代码:
console.log(typeof Cat);// function console.log(Cat.prototype.constructor ===Cat);//true
class类是构造函数的另一种写法,仍然存在prototype方法
console.log(Cat.prototype);//object
可以通过原型prototype修改类方法和新增方法
Cat.prototype.Say = function(){ return return '我的名字是' + this.name+',我是原型prototype声明同样的Say方法,把原有Say方法覆盖了'; } cat2 = new Cat('年年',5); console.log(cat2.Say());//我的名字是年年,我是原型prototype声明同样的Say方法,把原有Say方法覆盖了 Cat.prototype.Go = function(){ return return '我的年龄是' + this.age; } console.log(cat2.Go());//我的年龄是5
还可以通过Object.assign方法来为对象动态增加方法
Object.assign(Cat.prototype,{ Eat:function(){ return this.name; }, Run:function(){ return this.age; } }) cat3 =new Cat('卡卡',4); console.log(cat3.Eat());//卡卡 console.log(cat3.Run());//4
也可以使用实例对象的__proto__属性新增类的方法
cat3 =new Cat('卡卡',4); cat4 =new Cat('楼楼',10); cat3.__proto__.Play = function(){ return this.name; } console.log(cat3.Play());// 卡卡 console.log(cat4.Play());// 楼楼
三、实例属性和原型属性
实例属性:constructor里面的属性为实例属性,即定义在this对象上
原型属性:除去实例属性都称为原型属性,即定义在class类上
hasOwnProperty方法:可以通过hasOwnProperty()方法进行判断属性是否是实例属性
in操作符:能够访问到属性时返回true,无论是实例属性还是原型属性
class Person(){ constructor(per1,per2){ this.per1 = per1; this.per2 = per2; } Say(){ return per1+per2; } } var box=new Person('年年','有鱼'); console.log(Person.hasOwnProperty("per1"));//true console.log(Person.hasOwnProperty("per2"));//true console.log(Person.hasOwnProperty("Say"));//false console.log("per1" in Person);//true console.log("per2" in Person);//true console.log("Say" in Person);//true console.log("Go" in Person);//false
四、class类的继承
通过extends关键字实现类的继承
class Person{ constructor(name,age){ this.name = name; this.age = age; } getName(){ return this.name; } getAge(){ return this.age; } } class Student extends Person{ getName(){ return '我覆盖了父级的方法,'+ this.name; } getScore(){ return '我是子级新增的方法,'+this.name; } } var stu1 = new Student('有鱼',2); console.log(sut1.getName());// 我覆盖了父级的方法,有鱼 console.log(sut1.getAge());//2 console.log(sut1.getScore());// 我是子级新增的方法,有鱼
通过super关键字进行拓展父类构造器或方法
super作用:
①子类使用构造器constructor的时候,必须使用super关键字,用来扩展构造器
②子类同名方法会覆盖父类同名方法,使用super关键字后则可以调用到父类的同名函数
class Person{ constructor(name){ this.name = name; } getName(){ console.log('我是父级类getName方法输出来的'); } getAge(){ console.log(this.age); } } class Student extends Person{ constructor(name,age,sex){ super();//必须先调用super,才能使用constructor,才能使用this对象 this.name = name; this.age = age; this.sex = sex; } getName(){ super.getName();//调用super,才能调用父类同名函数getName console.log('我是子级类getName方法输出来的'); } } var stu1 = new Student('有鱼',2); stu1.getName(); // 我是父级类getName方法输出来的 // 我是子级类getName方法输出来的
static关键字的使用
①static关键字是类的方法
②只能通过类名来调用,不能被实例对象调用
③static方法也可以被继承
class Person{ constructor(name,age){ this.name = name; this.age = age; } static getAge(){ console.log('我是静态属性static'); } } class Student extends Person{} var stu1 = new Student('有鱼',2); Person.getAge();//我是静态属性static Student.getAge();//我是静态属性static stu1.getAge();//stu1.getAge is not a function
原文地址:https://segmentfault.com/a/1190000021704238
相关推荐
-
js运行机制和事件循环 javascript/jquery
2019-10-14
-
手摸手教你使用WebSocket[其实WebSocket也不难] javascript/jquery
2018-10-25
-
想进美团不知道选哪个技术岗位?这里有一份通关秘籍! javascript/jquery
2020-6-12
-
玩玩Flutter的拖拽——实现一款万能遥控器 javascript/jquery
2020-6-27
-
在Typescript项目中,如何优雅的使用ESLint和Prettier javascript/jquery
2019-7-7
-
git 入门教程之 git 私服搭建教程 javascript/jquery
2019-3-31
-
浏览器渲染原理 javascript/jquery
2019-5-14
-
【第2期】前端算法精选-字符串系列 javascript/jquery
2020-5-28
-
前端工程化 – 剖析npm的包管理机制 javascript/jquery
2020-6-11
-
怎样使你的 JavaScript 代码简单易读 javascript/jquery
2019-4-15