//定义类class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; }}
class Rectangle { constructor(height, width) { this.height = height; this.width = width; }}
var obj = new Myclass(); //报错class Myclass (){ }
{ let B = class {}; // let 声明 不存在函数提高 class A extends B { //若是存在类哈函数提高的话,这行会提高到第一行,父亲还没声明,儿子怎么继承? } }
class f1 {}; class f1 {}; var f2 = class {}; class f2 {}; // 报错了 class f3 {}; var f3 = class {}; // 报错了 var f4 = class {}; var f4 = class {}; // 若是两个函数表达式重名了,那么不会报错
var myClass = class [className] [extends] { // class body}
// 方式一const MyClass = class {};// 方式二:给出类名const MyClass = class Me { getClassName() { return Me.name; }};
var Foo = class { constructor() {} bar() { return 'Hello World!'; }};var instance = new Foo();instance.bar(); // "Hello World!"Foo.name; // "Foo"
var Foo = class NamedFoo { constructor() {} whoIsThere() { return NamedFoo.name; }}var bar = new Foo();bar.whoIsThere(); // "NamedFoo"NamedFoo.name; // ReferenceError: NamedFoo is not definedFoo.name; // "NamedFoo"
let person = new class { constructor(name) { this.name = name; } sayName() { console.log(this.name); }}('Zhang San');person.sayName(); // Zhang San
一个类只能拥有一个名为constructor
的方法(不然会报错),一个类的 constructor 方法只有在实例化的时候被调用。javascript
若是没有显式定义constructor
方法,这个方法会被默认添加,即,无论有没有显示定义,任何一个类都有constructor
方法。
html
子类必须在constructor方法中调用super
方法,不然新建实例时会报错。由于子类没有本身的this
对象,而是继承父类的this
对象,而后对其进行加工,若是不调用super
方法,子类就得不到this
对象。
java
class Point {}class ColorPoint extends Point { constructor() {}}let cp = new ColorPoint(); // ReferenceError
ColorPoint
继承了父类
Point
,可是它的构造函数没有调用
super
方法,致使新建实例时报错。
定义类的方法时,方法名前面不须要加上function
关键字。另外,方法之间不须要用逗号分隔,加了会报错。es6
class Bar { constructor() {} doStuff() {} toString() {} toValue() {}}
Bar.prototype = { doStuff() {}, toString() {}, toValue() {}};
prototype
上面,因此类的新方法能够添加在
prototype
对象上面。
Object.assign
方法能够很方便地一次向类添加多个方法。
class Point { constructor() { // ... }}Object.assign(Point.prototype, { toString() {}, toValue() {}});
class Point { constructor(x, y) { // ... } toString() { return '(' + x + ', ' + y + ')'; }}Object.keys(Point.prototype); // []Object.getOwnPropertyNames(Point.prototype); // ["constructor", "toString"]Object.getOwnPropertyDescriptor(Point, 'toString');// Object {writable: true, enumerable: false, configurable: true}
static
关键字用来定义类的静态方法。静态方法是指那些不须要对类进行实例化,使用类名就能够直接访问的方法。静态方法常常用来做为工具函数。
class Point { constructor(x, y) { this.x = x; this.y = y; } static distance(a, b) { const dx = a.x - b.x; const dy = a.y - b.y; return Math.sqrt(dx*dx + dy*dy); }}const p1 = new Point(5, 5);const p2 = new Point(10, 10);console.log(Point.distance(p1, p2));
静态方法不能够被实例继承,是经过类名直接调用的。可是,父类的静态方法能够被子类继承。express
class Foo { static classMethod() { return 'hello'; }}class Bar extends Foo {}Bar.classMethod(); // "hello"
extends
关键字用于实现类之间的继承。子类继承父类,就继承了父类的全部属性和方法。 extends
后面只能够跟一个父类。babel
class ColorPoint extends Point { constructor(x, y, color) { super(x, y); // 调用父类的constructor(x, y) this.color = color; } toString() { return this.color + ' ' + super.toString(); // 调用父类的toString() }}
extends
关键字不能用于继承一个对象,若是你想继承自一个普通的对象,你必须使用 Object.setPrototypeof ( )
//先来个父类,带些属性 function Super(){ this.flag = true; } //为了提升复用性,方法绑定在父类原型属性上 Super.prototype.getFlag = function(){ return this.flag; } //来个子类 function Sub(){ this.subFlag = false; } //实现继承 Sub.prototype = new Super; //给子类添加子类特有的方法,注意顺序要在继承以后 Sub.prototype.getSubFlag = function(){ return this.subFlag; } //构造实例 var es5 = new Sub;
function Super(){ this.flag = true; } Super.prototype.getFlag = function(){ return this.flag; //继承方法 } function Sub(){ this.subFlag = flase Super.call(this) //继承属性 } Sub.prototype = new Super; var obj = new Sub(); Sub.prototype.constructor = Sub; Super.prototype.getSubFlag = function(){ return this.flag; }
Sub.prototype.constructor = Sub;
function _inherits(subClass, superClass) { // 确保superClass为function if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } // 把子类.prototype 继承了父类.prototype(new 父类), 同时把子类prototype的constructor进行了重写; // 给subClass添加constructor这个属性 subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); // 将父类设为子类的prototype if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;}
子类.prototype = new 父类
function Car (desc) { this.desc = desc; this.color = "red";} Car.prototype = { getInfo: function() { return 'A ' + this.color + ' ' + this.desc + '.'; }};//instantiate object using the constructor functionvar car = Object.create(Car.prototype);car.color = "blue";alert(car.getInfo()); //displays 'A blue undefined.' ??! // 看见了吧,只会继承方法,不能继承属性
var Car2 = Object.create(null); //this is an empty object, like {}Car2.prototype = { getInfo: function() { return 'A ' + this.color + ' ' + this.desc + '.'; }}; var car2 = Object.create(Car2.prototype, { //value properties color: { writable: true, configurable:true, value: 'red' }, //concrete desc value rawDesc: { writable: false, configurable:true, value: 'Porsche boxter' }, // data properties (assigned using getters and setters) desc: { configurable:true, get: function () { return this.rawDesc.toUpperCase(); }, set: function (value) { this.rawDesc = value.toLowerCase(); } }}); car2.color = 'blue';alert(car2.getInfo()); //displays 'A RED PORSCHE BOXTER.'
var _this = _possibleConstructorReturn(this, (b.__proto__ || Object.getPrototypeOf(b)).call(this));
class A extends Object {}A.__proto__ === Object // trueA.prototype.__proto__ === Object.prototype // true
class A {}A.__proto__ === Function.prototype // trueA.prototype.__proto__ === Object.prototype // true
class C extends null { constructor() { return Object.create(null); }}
class A extends B {}A.__proto__ === B; //继承属性A.prototype.__proto__ === B.prototype; //继承方法
子类.prototype = Object.create (父类.prototype) // 至关于 new 父类
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
var p1 = new Point(2,3);var p2 = new Point(3,2);p1.__proto__ === p2.__proto__
var p1 = new Point(2,3);var p2 = new Point(3,2);p1.__proto__.printName = function () { return 'Oops' };p1.printName() // "Oops"p2.printName() // "Oops"var p3 = new Point(4,2);p3.printName() // "Oops"
super
关键字能够用来调用其父类的构造器或方法。super 做为方法的时候,必须在 constructor 中调用,而且只能在 constructor 里面被调用app
class Cat { constructor(name) { this.name = name; } speak() { console.log(this.name + ' makes a noise.'); }}class Lion extends Cat { speak() { super.speak(); console.log(this.name + ' roars.'); }}
class A { p() { return 2; }}class B extends A { constructor() { super(); console.log(super.p()); // 2 }}let b = new B();
class A { constructor() { this.x = 1; } print() { console.log(this.x); }}class B extends A { constructor() { super(); this.x = 2; } m() { super.print(); }}let b = new B();b.m() // 2
class A { constructor() { this.x = 1; }}class B extends A { constructor() { super(); this.x = 2; super.x = 3; console.log(super.x); // undefined console.log(this.x); // 3 }}let b = new B();
class Parent { static myMethod(msg) { console.log('static', msg); } myMethod(msg) { console.log('instance', msg); }}class Child extends Parent { static myMethod(msg) { super.myMethod(msg); } myMethod(msg) { super.myMethod(msg); }}Child.myMethod(1); // static 1var child = new Child();child.myMethod(2); // instance 2
class A {}class B extends A { constructor() { super(); console.log(super); // 报错 }}
与ES5同样,在类内部可使用get
和set
关键字,对某个属性设置取值和赋值方法。函数
class Foo { constructor() {} get prop() { return 'getter'; } set prop(val) { console.log('setter: ' + val); }}let foo = new Foo();foo.prop = 1;// setter: 1foo.prop;// "getter"
prop
属性有对应 的赋值和取值方法,所以赋值和读取行为都被自定义了。
var descriptor = Object.getOwnPropertyDescriptor(Foo.prototype, 'prop');"get" in descriptor // true"set" in descriptor // true
prop
属性的描述对象上的,这与ES5一致。
若是类的某个方法名前加上星号(*
),就表示这个方法是一个Generator函数。工具
class Foo { constructor(...args) { this.args = args; } * [Symbol.iterator]() { for (let arg of this.args) { yield arg; } }}for (let x of new Foo('hello', 'world')) { console.log(x);}// hello// world
for...of
循环会自动调用这个遍历器。
function Person(name) { if (new.target !== undefined) { this.name = name; } else { throw new Error('必须使用new生成实例'); }}// 另外一种写法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 Rectangle { constructor(length, width) { console.log(new.target === Rectangle); // ... }}class Square extends Rectangle { constructor(length) { super(length, length); // 至关于执行父类中的constructor, }}var obj = new Square(3); // 输出 false
class Shape { constructor() { if (new.target === Shape) { throw new Error('本类不能实例化'); // 抛出一个错误 } }}class Rectangle extends Shape { constructor(length, width) { super(); // ... }}var x = new Shape(); // 报错var y = new Rectangle(3, 4); // 正确