class
基本语法
ES6引入Class
这个概念,作为对象模板。
Copy //es5
function PersonType (name) {
this .name = name;
}
PersonType . prototype . sayName = function () {
console .log ( this .name);
};
let person = new PersonType ( "Nicholas" );
person .sayName (); // 输出 "Nicholas"
//ES6
class PersonClass {
// 等价于 PersonType 构造器
constructor (name) {
this .name = name;
}
// 等价于 PersonType.prototype.sayName
sayName () {
console .log ( this .name);
}
}
let person = new PersonClass ( "Nicholas" );
person .sayName (); // 输出 "Nicholas"
ES5的构造函数Point
,对应ES6的Point
类的构造方法。
构造函数的prototype
属性,在ES6的“类”上面继续存在。
Copy class Point {
constructor (){
// ...
}
toString (){
// ...
}
toValue (){
// ...
}
}
// 等同于
Point . prototype = {
toString (){} ,
toValue (){}
};
prototype
对象的constructor
属性,直接指向“类”的本身。
Copy Point . prototype . constructor === Point // true
constructor方法
constructor
方法是类的默认方法,通过new
命令生成对象实例时,自动调用该方法。
constructor
方法默认返回实例对象(即this
),完全可以指定返回另外一个对象。
Copy class Foo {
constructor () {
return Object .create ( null );
}
}
new Foo () instanceof Foo
// false
类的实例对象
类的调用的要加上new
,类的所有实例共享一个原型对象。
Copy 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"
this的指向
类的方法内部如果含有this
,它默认指向类的实例。
Copy class Logger {
printName (name = 'there' ) {
this .print ( `Hello ${ name } ` );
}
print (text) {
console .log (text);
}
}
const logger = new Logger ();
logger .printName ();
//Hello there
Class的继承
Class之间可以通过extends
关键字实现继承。
Copy class Point {
constructor (x , y , color){
this .x = x;
this .y = y;
this .color = color;
}
chooseColor (){
console .log ( 'color:' , this .color);
}
}
class ColorPoint extends Point {
constructor () {
super ( 1 , 2 , 'blue' );
}
toString (){
return 'ColorPoint:' + super.color
}
}
var cp =new ColorPoint ();
cp .chooseColor ()
//VM2425:8 color: blue
super
表示父类的构造函数,新建父类的this
对象。子类没有调用,会报错。
类的prototype属性和__proto__属性
子类的__proto__
属性,表示构造函数的继承,总是指向父类。
子类prototype
属性的__proto__
属性,表示方法的继承,总是指向父类的prototype
属性。
Copy class A {
}
class B extends A {
}
B . __proto__ === A // true
B . prototype . __proto__ === A . prototype // true
Extends 的继承目标
子类继承Object类。
Copy class A extends Object {
}
A . __proto__ === Object // true
A . prototype . __proto__ === Object . prototype // true
A
其实就是构造函数Object
的复制,A
的实例就是Object
的实例。
不存在任何继承。
Copy class A {
}
A . __proto__ === Function . prototype // true
A . prototype . __proto__ === Object . prototype // true
这种情况下,A
作为一个基类(即不存在任何继承),就是一个普通函数,所以直接继承Funciton.prototype
。调用后返回空对象,指向造函数(Object)的prototype
属性。
子类继承null。
Copy class A extends null {
}
A . __proto__ === Function . prototype // true
A . prototype . __proto__ === undefined // true
super
super
代表父类A
的构造函数,返回子类b
的实例。 spuer
内部this
指向B
。
Copy class A {
constructor () {
console .log ( new . target .name);
}
}
class B extends A {
constructor () {
super ();
}
}
new A () // A
new B () // B
super
作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
通过super
调用父类的方法时,super
会绑定子类的this
。
Copy class A {
constructor () {
this .x = 1 ;
}
print () {
console .log ( this .x);
}
}
class B extends A {
constructor () {
super ();
this .x = 2 ;
}
m () {
super.print ();
//new A().print.call(this);
}
}
let b = new B ();
b .m () // 2
实例的__proto__属性
子类实例的__proto__属性的__proto__属性,指向父类实例的__proto__属性。也就是说,子类的原型的原型,是父类的原型。
Copy var p1 = new Point ( 2 , 3 );
var p2 = new ColorPoint ( 2 , 3 , 'red' );
p2 . __proto__ === p1 . __proto__ // false
p2 . __proto__ . __proto__ === p1 . __proto__ // true
Class的取值函数(getter)和存值函数(setter)
Copy class MyClass {
constructor () {
// ...
}
get prop () {
return 'getter' ;
}
set prop (value) {
console .log ( 'setter: ' + value);
}
}
let inst = new MyClass ();
inst .prop = 123 ;
// setter: 123
inst .prop
// 'getter'
prop
属性有对应的存值函数和取值函数,因此赋值和读取行为都被自定义了。
Class 的 Generator 方法
Copy 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
Foo类的Symbol.iterator
方法前有一个星号,表示该方法是一个 Generator 函数。Symbol.iterator
方法返回一个Foo类的默认遍历器
Class 的静态方法
如果在一个方法前,加上static
关键字,就表示该方法不会被实例继承,而是直接通过类来调用。父类的静态方法,能被子类继承。也可以在super
上调用。
Copy class Foo {
static classMethod () {
return 'hello' ;
}
}
Foo .classMethod () // 'hello'
var foo = new Foo ();
foo .classMethod ()
// TypeError: foo.classMethod is not a function
ES6只用静态方法,没有静态属性。
new.target属性
new
命令作用于的那个构造函数,子类继承父类时,new.target
会返回子类。
Copy class Rectangle {
constructor (length , width) {
console .log ( new . target === Rectangle);
this . length = length;
this .width = width;
}
}
var obj = new Rectangle ( 3 , 4 ); // 输出 true
Mixin模式的实现
Mixin
模式指的是,将多个类的接口“混入”(mix in)另一个类。
Copy function mix ( ... mixins) {
class Mix {}
for ( let mixin of mixins) {
copyProperties (Mix , mixin);
copyProperties ( Mix . prototype , mixin . prototype );
}
return Mix;
}
function copyProperties (target , source) {
for ( let key of Reflect .ownKeys (source)) {
if ( key !== "constructor"
&& key !== "prototype"
&& key !== "name"
) {
let desc = Object .getOwnPropertyDescriptor (source , key);
Object .defineProperty (target , key , desc);
}
}
}
class DistributedEdit extends mix (Loggable , Serializable) {
// ...
}
上面代码的mix
函数,可以将多个对象合成为一个类。