es6中class的理解(Understanding of class in ES6)

 1 //函数名和实例化构造名相同且大写(非强制,但这么写有助于区分构造函数和普通函数)
 2 function Person(name,age) {
 3     this.name = name;
 4     this.age=age;
 5 }
 6 Person.prototype.say = function(){
 7     return "我的名字叫" + this.name+"今年"+this.age+"岁了";
 8 }
 9 var obj=new Person("laotie",88);//通过构造函数创建对象,必须使用new 运算符
10 console.log(obj.say());//我的名字叫laotie今年88岁了

  构造函数生成实例的执行过程:

  • 当使用了构造函数,并且new 构造函数(),后台会隐式执行new Object()创建对象;
  • 将构造函数的作用域给新对象,(即new Object()创建出的对象),而函数体内的this就代表new Object()出来的对象。
  • 执行构造函数的代码。
  • 返回新对象(后台直接返回);
  ES6引入了Class(类)这个概念,通过class关键字可以定义类。该关键字的出现使得其在对象写法上更加清晰,更像是一种面向对象的语言。如果将之前的代码改为ES6的写法就会是这个样子:
 1 class Person{//定义了一个名字为Person的类
 2     constructor(name,age){//constructor是一个构造方法,用来接收参数
 3         this.name = name;//this代表的是实例对象
 4         this.age=age;
 5     }
 6     say(){//这是一个类的方法,注意千万不要加上function
 7         return "我的名字叫" + this.name+"今年"+this.age+"岁了";
 8     }
 9 }
10 var obj=new Person("laotie",88);
11 console.log(obj.say());//我的名字叫laotie今年88岁了

  注意:

  1.在类中声明方法的时候,千万不要给该方法加上function关键字
  2.方法之间不要用逗号分隔,否则会报错 由下面代码可以看出类实质上就是一个函数。类自身指向的就是构造函数。所以可以认为ES6中的类其实就是构造函数的另外一种写法!
1 console.log(typeof Person);//function
2 console.log(Person===Person.prototype.constructor);//true

  类的所有方法都定义在类的prototype属性上

1 Person.prototype.say=function(){//定义与类中相同名字的方法。成功实现了覆盖!
2     return "我是来证明的,你叫" + this.name+"今年"+this.age+"岁了";
3 }
4 var obj=new Person("laotie",88);
5 console.log(obj.say());//我是来证明的,你叫laotie今年88岁了

  当然也可以通过prototype属性对类添加方法

1 Person.prototype.addFn=function(){
2     return "我是通过prototype新增加的方法,名字叫addFn";
3 }
4 var obj=new Person("laotie",88);
5 console.log(obj.addFn());//我是通过prototype新增加的方法,名字叫addFn

  还可以通过Object.assign方法来为对象动态增加方法

 1 Object.assign(Person.prototype,{
 2     getName:function(){
 3         return this.name;
 4     },
 5     getAge:function(){
 6         return this.age;
 7     }
 8 })
 9 var obj=new Person("laotie",88);
10 console.log(obj.getName());//laotie
11 console.log(obj.getAge());//88

  constructor方法是类的构造函数的默认方法,通过new命令生成对象实例时,自动调用该方法。

1 class Box{
2     constructor(){
3         console.log("啦啦啦,今天天气好晴朗");//当实例化对象时该行代码会执行。
4     }
5 }
6 var obj=new Box();

  constructor方法如果没有显式定义,会隐式生成一个constructor方法。所以即使你没有添加构造函数,构造函数也是存在的。constructor方法默认返回实例对象this,但是也可以指定constructor方法返回一个全新的对象,让返回的实例对象不是该类的实例。

 1 class Box{
 2     constructor(num1,num2){
 3         this.num1 = num1;
 4         this.num2=num2;
 5     }
 6     sum(){
 7         return num1+num2;
 8     }
 9 }
10 var box=new Box(12,88);
11 console.log(box.hasOwnProperty("num1"));//true
12 console.log(box.hasOwnProperty("num2"));//true
13 console.log(box.hasOwnProperty("sum"));//false
14 console.log("num1" in box);//true
15 console.log("num2" in box);//true
16 console.log("sum" in box);//true
17 console.log("say" in box);//false

  类的所有实例共享一个原型对象,它们的原型都是Person.prototype,所以proto属性是相等的

 1 class Box{
 2     constructor(num1,num2){
 3         this.num1 = num1;
 4         this.num2=num2;
 5     }
 6     sum(){
 7         return num1+num2;
 8     }
 9 }
10 //box1与box2都是Box的实例。它们的__proto__都指向Box的prototype
11 var box1=new Box(12,88);
12 var box2=new Box(40,60);
13 console.log(box1.__proto__===box2.__proto__);//true

  由此,也可以通过proto来为类增加方法。使用实例的proto属性改写原型,会改变Class的原始定义,影响到所有实例,所以不推荐使用!

 1 class Box{
 2     constructor(num1,num2){
 3         this.num1 = num1;
 4         this.num2=num2;
 5     }
 6     sum(){
 7         return num1+num2;
 8     }
 9 }
10 var box1=new Box(12,88);
11 var box2=new Box(40,60);
12 box1.__proto__.sub=function(){
13     return this.num2-this.num1;
14 }
15 console.log(box1.sub());//76
16 console.log(box2.sub());//20

  class不存在变量提升,所以需要先定义再使用。因为ES6不会把类的声明提升到代码头部,但是ES5就不一样,ES5存在变量提升,可以先使用,然后再定义。

 1 //ES5可以先使用再定义,存在变量提升
 2 new A();
 3 function A(){
 4 
 5 }
 6 //ES6不能先使用再定义,不存在变量提升 会报错
 7 new B();//B is not defined
 8 class B{
 9 
10 }
————————
 1 //函数名和实例化构造名相同且大写(非强制,但这么写有助于区分构造函数和普通函数)
 2 function Person(name,age) {
 3     this.name = name;
 4     this.age=age;
 5 }
 6 Person.prototype.say = function(){
 7     return "我的名字叫" + this.name+"今年"+this.age+"岁了";
 8 }
 9 var obj=new Person("laotie",88);//通过构造函数创建对象,必须使用new 运算符
10 console.log(obj.say());//我的名字叫laotie今年88岁了

Execution process of constructor generation instance:

  • When the constructor is used and the new constructor () is used, the background will implicitly execute new object () to create the object;
  • The scope of the constructor is given to the new object (that is, the object created by new object()), and this in the function body represents the object created by new object().
  • Execute the code of the constructor.
  • Return a new object (returned directly in the background);
  ES6引入了Class(类)这个概念,通过class关键字可以定义类。该关键字的出现使得其在对象写法上更加清晰,更像是一种面向对象的语言。如果将之前的代码改为ES6的写法就会是这个样子:
 1 class Person{//定义了一个名字为Person的类
 2     constructor(name,age){//constructor是一个构造方法,用来接收参数
 3         this.name = name;//this代表的是实例对象
 4         this.age=age;
 5     }
 6     say(){//这是一个类的方法,注意千万不要加上function
 7         return "我的名字叫" + this.name+"今年"+this.age+"岁了";
 8     }
 9 }
10 var obj=new Person("laotie",88);
11 console.log(obj.say());//我的名字叫laotie今年88岁了

< strong > note: < / strong >

  1.在类中声明方法的时候,千万不要给该方法加上function关键字
  2.方法之间不要用逗号分隔,否则会报错 由下面代码可以看出类实质上就是一个函数。类自身指向的就是构造函数。所以可以认为ES6中的类其实就是构造函数的另外一种写法!
1 console.log(typeof Person);//function
2 console.log(Person===Person.prototype.constructor);//true

All methods of the class are defined on the prototype attribute of the class

1 Person.prototype.say=function(){//定义与类中相同名字的方法。成功实现了覆盖!
2     return "我是来证明的,你叫" + this.name+"今年"+this.age+"岁了";
3 }
4 var obj=new Person("laotie",88);
5 console.log(obj.say());//我是来证明的,你叫laotie今年88岁了

Of course, you can also add methods to the class through the prototype attribute

1 Person.prototype.addFn=function(){
2     return "我是通过prototype新增加的方法,名字叫addFn";
3 }
4 var obj=new Person("laotie",88);
5 console.log(obj.addFn());//我是通过prototype新增加的方法,名字叫addFn

You can also use object Assign method to dynamically add methods to the object

 1 Object.assign(Person.prototype,{
 2     getName:function(){
 3         return this.name;
 4     },
 5     getAge:function(){
 6         return this.age;
 7     }
 8 })
 9 var obj=new Person("laotie",88);
10 console.log(obj.getName());//laotie
11 console.log(obj.getAge());//88

The constructor method is the default method of the constructor of the class. It is called automatically when an object instance is generated by the new command.

1 class Box{
2     constructor(){
3         console.log("啦啦啦,今天天气好晴朗");//当实例化对象时该行代码会执行。
4     }
5 }
6 var obj=new Box();

If the constructor method is not explicitly defined, it will implicitly generate a constructor method. So even if you don’t add a constructor, the constructor still exists. The constructor method returns the instance object this by default, but you can also specify the constructor method to return a new object so that the returned instance object is not an instance of this class.

 1 class Box{
 2     constructor(num1,num2){
 3         this.num1 = num1;
 4         this.num2=num2;
 5     }
 6     sum(){
 7         return num1+num2;
 8     }
 9 }
10 var box=new Box(12,88);
11 console.log(box.hasOwnProperty("num1"));//true
12 console.log(box.hasOwnProperty("num2"));//true
13 console.log(box.hasOwnProperty("sum"));//false
14 console.log("num1" in box);//true
15 console.log("num2" in box);//true
16 console.log("sum" in box);//true
17 console.log("say" in box);//false

All instances of the class share a prototype object, and their prototype is person Prototype, so the proto attribute is equal

 1 class Box{
 2     constructor(num1,num2){
 3         this.num1 = num1;
 4         this.num2=num2;
 5     }
 6     sum(){
 7         return num1+num2;
 8     }
 9 }
10 //box1与box2都是Box的实例。它们的__proto__都指向Box的prototype
11 var box1=new Box(12,88);
12 var box2=new Box(40,60);
13 console.log(box1.__proto__===box2.__proto__);//true

Thus, you can also add methods to classes through proto. Rewriting the prototype with the proto attribute of the instance will change the original definition of class and affect all instances, so it is not recommended!

 1 class Box{
 2     constructor(num1,num2){
 3         this.num1 = num1;
 4         this.num2=num2;
 5     }
 6     sum(){
 7         return num1+num2;
 8     }
 9 }
10 var box1=new Box(12,88);
11 var box2=new Box(40,60);
12 box1.__proto__.sub=function(){
13     return this.num2-this.num1;
14 }
15 console.log(box1.sub());//76
16 console.log(box2.sub());//20

< strong > class does not have variable promotion < / strong >, so it needs to be defined before use. Because ES6 does not promote the class declaration to the code header, but Es5 is different. Es5 has variable promotion, which can be used first and then defined.

 1 //ES5可以先使用再定义,存在变量提升
 2 new A();
 3 function A(){
 4 
 5 }
 6 //ES6不能先使用再定义,不存在变量提升 会报错
 7 new B();//B is not defined
 8 class B{
 9 
10 }