1,构造函数
function Point(x, y) { this.x = x; this.y = y; } Point.prototype.toString = function () { return '(' + this.x + ', ' + this.y + ')'; }; var p = new Point(1, 2); console.log(p) console.log(p.toString) 效果等同于 function Point(x, y) { this.x = x; this.y = y; this.toString = function () { return '(' + this.x + ', ' + this.y + ')'; }; } var p = new Point(1, 2); console.log(p) console.log(p.toString) 但是意义不一样,前者定义在生成对象的原型中; 后者直接定义在属性中
结果:
可见:
1、构造函数也是一个普通函数,创建方式和普通函数一样,但构造函数习惯上首字母大写 2、构造函数和普通函数的区别在于:调用方式不一样。作用也不一样(构造函数用来新建实例对象) 3、调用方式不一样。 a. 普通函数的调用方式:直接调用 person(); b.构造函数的调用方式:需要使用new关键字来调用 new Person(); 4、构造函数的函数名与类名相同:Person( ) 这个构造函数,Person 既是函数名,也是这个对象的类名 5、内部用this 来构造属性和方法
2,class:
ES6 的class
可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class
写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。下面的代码等同于以上es5的第一种写法。
class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } }
上面代码定义了一个“类”,可以看到里面有一个constructor
方法,这就是构造方法,而this
关键字则代表实例对象。也就是说,ES5 的构造函数Point
,对应 ES6 的Point
类的构造方法。
Point
类除了构造方法,还定义了一个toString
方法。注意,定义“类”的方法的时候,前面不需要加上function
这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。
ES6 的类,完全可以看作构造函数的另一种写法。
class Point { // ... } typeof Point // "function" Point === Point.prototype.constructor // true
上面代码表明,类的数据类型就是函数,类本身就指向构造函数。
使用的时候,也是直接对类使用new
命令,跟构造函数的用法完全一致。
class Bar { doStuff() { console.log('stuff'); } } var b = new Bar(); b.doStuff() // "stuff"
构造函数的prototype
属性,在 ES6 的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype
属性上面。
class Point { constructor() { // ... } toString() { // ... } toValue() { // ... } } // 等同于 Point.prototype = { constructor() {}, toString() {}, toValue() {}, };
在类的实例上面调用方法,其实就是调用原型上的方法。
class B {} let b = new B(); b.constructor === B.prototype.constructor // true
上面代码中,b
是B
类的实例,它的constructor
方法就是B
类原型的constructor
方法。
2.1 Object.assign添加class方法
由于类的方法都定义在prototype
对象上面,所以类的新方法可以添加在prototype
对象上面。Object.assign
方法可以很方便地一次向类添加多个方法。
class Point { constructor(){ // ... } } Object.assign(Point.prototype, { toString(){}, toValue(){} });
2.2静态方法:static
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static
关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
class Foo { static classMethod() { return 'hello'; } } Foo.classMethod() // 'hello' var foo = new Foo(); foo.classMethod() // TypeError: foo.classMethod is not a function
上面代码中,Foo
类的classMethod
方法前有static
关键字,表明该方法是一个静态方法,可以直接在Foo
类上调用(Foo.classMethod()
),而不是在Foo
类的实例上调用。如果在实例上调用静态方法,会抛出一个错误,表示不存在该方法。
注意,如果静态方法包含this
关键字,这个this
指的是类,而不是实例。
(类的方法内部如果含有this
,它默认指向类的实例。但是,必须非常小心,一旦单独使用该方法,很可能报错。
解决方案:1,在构造方法中绑定this;2,使用箭头函数;3,使用
)Proxy
class Foo { static bar() { this.baz(); } static baz() { console.log('hello'); } baz() { console.log('world'); } } Foo.bar() // hello
上面代码中,静态方法bar
调用了this.baz
,这里的this
指的是Foo
类,而不是Foo
的实例,等同于调用Foo.baz
。另外,从这个例子还可以看出,静态方法可以与非静态方法重名。
父类的静态方法,可以被子类继承。
静态方法也是可以从super
对象上调用的。
2.3实例属性的新写法
2.4静态属性
2.5私有方法和私有属性
2.6new.target 属性
引用自 http://es6.ruanyifeng.com/#docs/class
可参考另一篇博文:https://www.cnblogs.com/wangtong111/p/11242557.html