【ES6】Class

以前采取构造函数+原型创建类

        function Point(x, y) { }
        Point.prototype.fn = function () { }
let p = new Point(1,2)

ES6使用class声明类

  1. 定义类的方法不用function关键字,方法之间不用逗号分隔
  2. 类内部采取严格模式,类不存在变量提升
  3. name属性 Point.name===Point
  4. 类内部this默认指向类的实例
        class Point {
            // 实例方法 p.exampleProp
            exampleProp = "实例属性"

            // constructor方法是类的默认方法,通过new命令生成实例对象自动调用该方法
// 没有显示定义会默认添加一个空的constructor // constructor方法默认return实例对象即this // Point.prototype.constructor === Point constructor(x, y) { this.x = x this.y = y console.log(this.x,this.y) } // 类内部使用get,set关键字对某个属性设置存执函数和取值函数拦截该属性的存取行为
// 其行为定义在Point.prototype上 // Object.getOwnPropertyDescriptor(Point.prototype,'prop') get prop() { console.log('getter') } set prop(val) { console.log('setter: ' + val); } // 类的方法直接定义在Point.prototype上,但是是不可遍历的 fn() { } // 静态属性和静态方法,不会被实例继承,直接通过类来调用如Point.staticProp。会被继承 static staticProp = '静态属性' static staticMethod() { } // 私有属性和方法,只能在类的内部访问,外部部分访问 #privateProp = "私有属性,只能在类的内部访问,外部无法访问" _privateMethod() { } } let p = new Point(1, 2) // 生成实例对象 p.__proto__ === Point.prototype === Object.getPrototypeOf(p)

new.target

  • 在构造中调用,如果不是通过new命令或者Reflect.constructor()调用,new.target会返回undefined
function Person(name) {
  if (new.target === Person) {
    this.name = name;
  } else {
    throw new Error('必须使用 new 命令生成实例');
  }
}

var person = new Person('张三'); // 正确
var notAPerson = Person.call(person, '张三');  // 报错
  • class内部调用new,target,返回当前class
  • 子类继承父类,new.target会返回子类
class Rectangle {
  constructor(length, width) {
    console.log(new.target === Rectangle);
    // ...
  }
}

class Square extends Rectangle {
  constructor(length, width) {
    super(length, width);
  }
}

var obj = new Square(3); // 输出 false
  • 可以构建不能独立使用、必须继承后才能使用的类,即在父的constructor中做判断,如果new.target为Father则抛出错误

继承

使用extends继承
        class Father {
            constructor(x, y) {
                this.x = x
                this.y = y
            }
        }

        class Children extends Father {
            constructor(x, y, z) {
                // super()在这里表示父类构造函数,必须在constructor方法中调用super()
                // 如果不调用supe方法,子类就得不到this对象
                // 子类自己的this对象必须通过父类的构造函数塑造,得到与父类同样的实例属性和方法,然后再进行加工,加上子类自己的实例属性和方法
                super(x, y) //相当于Father.prototype.constructor.call(Children)
                this.z = z
            }
            // super()作为函数只能在子类constructor方法中出现
            // 作为对象可以在子类普通方法中出现,指向父类的原型对象Father.prototype
            // 在静态方法中,指向父类
        }
        Object.getPrototypeOf(Children) === Father

__proto__

每个对象都有__proto__属性,指向对应的构造函数的原型。Class作为构造函数的语法糖,同时存在两条继承链

  1. 子类的__proto__属性,表示构造函数的继承,总是指向父类
  2. 子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性
        class A { }
        class B extends A { }
        B.__proto__ === A
        B.prototype.__proto === A.prototype

类的继承是按照下面的模式实现的

        class A { }
        class B { }
        Object.setPrototypeOf(B.prototype, A.prototype) //B实例继承A实例
        Object.setPrototypeOf(B, A); //B继承A的静态属性

  

 

  

 

posted @ 2020-02-10 00:13  把我当做一棵树叭  阅读(191)  评论(0)    收藏  举报