ES6中的class的详解

一、ES6构造函数生成实例对象

1.当使用了构造函数,并且new 构造函数(),后台会隐式执行new Object()创建对象;
2.将构造函数的作用域赋给新对象(即new Object()创建出的对象),而函数体内的this就代表new Object()出来的对象。
3.执行构造函数的代码。
4.返回新对象(后台直接返回);

class Person{ //定义了一个名字为Person的类
    constructor(name, age){//constructor是一个构造方法,用来接收参数
        this.name = name;//this代表的是实例对象
        this.age=age;
    }
    say(){//这是一个类的方法,注意千万不要加上function
        return "我的名字叫" + this.name+"今年"+this.age+"岁了";
    }
}
var obj=new Person("李大师", 30);
console.log(obj.say());//我的名字叫李大师今年30岁了

二、class解析

console.log(typeof Person); //function
console.log(Person === Person.prototype.constructor); //true

从这两段代码可以看书,其实Person类实质上就是一个函数。类自身指向的就是构造函数。所以可以认为ES6中的类其实就是构造函数的另外一种写法.

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

Person.prototype.addFn=function(){
    return "我是通过prototype新增加的方法,名字叫addFn";
}
var obj=new Person("李大师",30);
console.log(obj.addFn());
//我是通过prototype新增加的方法,名字叫addFn

除此之外,我们还可以通过Object.assign方法来为对象动态的增加方法,

Object.assign(Person.prototype, {
   getName : function() {
      return this.name
  },
  getAge : function() {
     return this.age
  }
})

var obj=new Person("李大师",30);
console.log(obj.getName());//李大师
console.log(obj.getAge());//30

三、constructor

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

// 啦啦啦,今天天气好晴朗

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

class Desk{
    constructor(){
        this.xixi="我是一只小小小小鸟!哦";
        return this
    }
}
class Box{
    constructor(){
       return new Desk();// 这里没有用this哦,直接返回一个全新的对象
    }
}
var obj=new Box();
console.log(obj.xixi);//我是一只小小小小鸟!哦

constructor 中定义的属性或方法与 constructorz外定义的属性或方法有什么区别呢?

class Person {
    constructor() {
        this.name = '李大师';
        this.age = 30;
        this.showName = function() {
             console.log(this.name)
        }
        this.showweight = function(){
            console.log(this.weight)
       }
    }

    height = 175;
    weight=70;
    sex = 'man';
    salary= 500000;
    showAge() {
       console.log(this.age)
    }
   
    showheight(){
      console.log(this.height)
   }

   showSex = function(){
      console.log(this.sex)
   }

   showSalary = ()=>{
      console.log(this.salary)
   }
} 

const person = new Person();

console.log(person.hasOwnProperty('name'));

// true

console.log(person.hasOwnProperty('name'));

// true

console.log(person.hasOwnProperty('height'));

// true

console.log(person.hasOwnProperty('weight'));

// true

console.log(person.hasOwnProperty('showName'));

// true

console.log(person.hasOwnProperty('showAge'));

// false

console.log(person.hasOwnProperty('showheight'));

// false
console.log(person.hasOwnProperty('showweight'));

// true

console.log(person.hasOwnProperty('showSex'));
// true
console.log(person.hasOwnProperty('showSalary'));
// true

从上面的代码我们可以看出

(1)无论是在constructor中,通过this.name = name 这种方式所绑定的属性和方法,最终会在实例对象中体现出来

(2)在constructor外部,通过showSex = function(){} 或者 showSalary = ()=>{} 这种方式绑定的方法,也会在实例对象中体现出来,有图为证
在这里插入图片描述
(3)在constructor外部,通过showAge(){} 这种方式绑定的方法,实际上是将方法绑定在了Person.prototype上面,有图为证
在这里插入图片描述
那么可以解释一个现象

Person.prototype.showAge()

// undefined

// 这个方法实际上输出的是undefined,因为Person.prototype上面并没有age这个属性

一句话来总结:class中,所有的属性,无论是否在contructor中指定,都会绑定到class的实例对象上;class中,通过showAge(){}这种方式绑定的方法,会默认的绑定到class的prototype属性上面去,并不会在class的实例对象上体现,而通过constructor中的this.showName = function(){} 或者constructor外部的 showSex = function(){} 这样的形式绑定的方法,将会绑定到class的实例对象上面去,在prototype上面并不会有体现。
根据上面的原则,我们可以发现,如果要定义一个class,那么对于那些需要在后代中继承的方法,可以通过showAge(){} 这样的形式,绑定到class的prototype属性上去,如果不需要在后代中继承,只需要在实例中使用的方法,就可以通过在constructor中定义,或者通过showSex = ()=>{} 这样的方式,绑定到它的实例对象中区。

四、继承

在ES6中,使用extends关键字来实现继承

class Animal  {
    constructor(){}

    name = 'animal';
    age = 3;

    showName() {
      console.log( 'animalName =' + this.name)
    }

    showAge = ()=>{
      console.log('animalAge = ' + this.age)
   }
}

class Dog extends Animal {
    constructor(){
     super()
   }
    name='dog';
    age=5;
    fullname = 'Dog';
    sex='male';
   
    showSex() {
      console.log(this.sex)
    }

    showName =()=> {
     console.log('name' + this.name)
   }

    showFullName(){
      console.log(this.name + this.fullname)
    }
}

const dog = new Dog();

dog.showAge();

//animalAge = 5 

dog.showName();
// namedog

dog.showSex();
// male

delete dog.showName

dog.showName()

// animalName =dog

我们可以发现,如果一个class的方法并不是定义在prototype方法上,而是像通过赋值一样showName = ()=>{} 这种方式,那么如果delete 了 实例对象上的属性,这个属性就会消失,再执行这个方法,就会向上访问它的原型 dog.proto 也就是Dog.prototype上去查找,但是Dog.prototype上面也是没有showName属性的,那么它只好向上查找,因为Dog是Animal的子类,Dog.prototype.proto === Animal.prototype, Animal.prototype上面是有showName属性的,那么可以得到最后一个结论,delete dog.showName之后 ,dog.showName() 会输出 animaleName =dog

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值