You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
之前已经对 ES5 中继承 有了深入的了解,Typescript、ES6 的代码会被编译成什么样子呢?可以在 Babel 官网的Try it out页面查看
es6
classPerson{constructor(name){this.name=name;}}
编译后
function_classCallCheck(instance,Constructor){if(!_instanceof(instance,Constructor)){thrownewTypeError("Cannot call a class as a function");}}varPerson=/*#__PURE__*/_createClass(functionPerson(name){_classCallCheck(this,Person);this.name=name;});
_classCallCheck 的作用是检查 Person 是否是通过 new 的方式调用,类必须使用 new 调用,否则会报错。当使用 var person = Person() 的形式调用的时候,this 指向 window,所以 instance instanceof Constructor 就会为 false
这也片面的说明 class 不仅仅是 原型继承的语法糖
es6
classPerson{constructor(name){this.name=name;}sayHello(){return"hello, I am "+this.name;}staticonlySayHello(){return"hello";}getname(){return"shane";}setname(newName){console.log("new name 为:"+newName);}}
编译后
"use strict";var_createClass=(function(){functiondefineProperties(target,props){for(vari=0;i<props.length;i++){vardescriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"indescriptor){descriptor.writable=true;}Object.defineProperty(target,descriptor.key,descriptor);}}returnfunction(Constructor,protoProps,staticProps){if(protoProps){defineProperties(Constructor.prototype,protoProps);}if(staticProps){defineProperties(Constructor,staticProps);}returnConstructor;};})();function_classCallCheck(instance,Constructor){if(!(instanceinstanceofConstructor)){thrownewTypeError("Cannot call a class as a function");}}varPerson=(function(){functionPerson(name){_classCallCheck(this,Person);this.name=name;}_createClass(Person,[{key: "sayHello",value: functionsayHello(){return"hello, I am "+this.name;},},{key: "name",get: functionget(){return"kevin";},set: functionset(newName){console.log("new name 为:"+newName);},},],[{key: "onlySayHello",value: functiononlySayHello(){return"hello";},},]);returnPerson;})();
"use strict";function_possibleConstructorReturn(self,call){if(!self){thrownewReferenceError("this hasn't been initialised - super() hasn't been called");}returncall&&(typeofcall==="object"||typeofcall==="function")
? call
: self;}function_inherits(subClass,superClass){if(typeofsuperClass!=="function"&&superClass!==null){thrownewTypeError("Super expression must either be null or a function, not "+typeofsuperClass);}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor: {value: subClass,enumerable: false,writable: true,configurable: true,},});if(superClass){Object.setPrototypeOf
? Object.setPrototypeOf(subClass,superClass)
: (subClass.__proto__=superClass);}}function_classCallCheck(instance,Constructor){if(!(instanceinstanceofConstructor)){thrownewTypeError("Cannot call a class as a function");}}varParent=functionParent(name){_classCallCheck(this,Parent);this.name=name;};varChild=(function(_Parent){_inherits(Child,_Parent);functionChild(name,age){_classCallCheck(this,Child);// 调用父类的 constructor(name)var_this=_possibleConstructorReturn(this,(Child.__proto__||Object.getPrototypeOf(Child)).call(this,name));_this.age=age;return_this;}returnChild;})(Parent);varchild1=newChild("kevin","18");console.log(child1);
_inherits
function_inherits(subClass,superClass){// extend 的继承目标必须是函数或者是 nullif(typeofsuperClass!=="function"&&superClass!==null){thrownewTypeError("Super expression must either be null or a function, not "+typeofsuperClass);}// 类似于 ES5 的寄生组合式继承,// 使用 Object.create,设置子类 prototype 属性的 __proto__ 属性指向父类的 prototype 属性// 并给子类添加一个可配置可写不可枚举的 constructor 属性,该属性值为 subClasssubClass.prototype=Object.create(superClass&&superClass.prototype,{constructor: {value: subClass,enumerable: false,writable: true,configurable: true,},});// 设置子类的 __proto__ 属性指向父类if(superClass){Object.setPrototypeOf
? Object.setPrototypeOf(subClass,superClass)
: (subClass.__proto__=superClass);}}
Object.create() 的第二个参数表示要添加到新创建对象的属性
_possibleConstructorReturn
function_possibleConstructorReturn(self,call){if(!self){thrownewReferenceError("this hasn't been initialised - super() hasn't been called");}returncall&&(typeofcall==="object"||typeofcall==="function")
? call
: self;}
typescript 中的 class 继承是基于 ES6 中 class 的扩展。因此可以类比 vanillajs 中基于原型的继承和 ES6 中的 class 继承的变化。其实,ES6 中的 class 继承其实就是 vanillajs 的语法糖,但又不仅仅是语法糖。
Class 基本语法
基本的类语法看起来像这样:
需要注意:
MyClass
是一个函数(提供作为constructor
的那个)methods
、getters
和settors
都被写入了 MyClass.prototype **prop
每个实例都有一份ES6 class 中没有直接定义到 prototype 上的属性的实现,可以借助 getter 和 setter 模拟共享属性
Class 继承
扩展一个类:
class Child extends Parent
在 extends 后允许任意表达式:
重写一个方法
Class 为此提供了 "super" 关键字:
重写一个 constructor
''继承类的 constructor 必须调用 super(...),并且一定要在使用 this 之前调用''
💡 为什么呢?
重写类字段
😨 一个棘手的注意要点;可以重写方法,也可以重写字段:
为什么会有这样的区别呢?
''这种字段与方法之间微妙的区别只特定于 JavaScript;这种行为仅在一个被重写的字段被父类构造器使用时才会显现出来;可以通过使用方法或者 getter/setter 替代类字段,来修复这个问题''
静态方法
静态属性
继承静态属性和方法
它是如何工作的?再次,使用原型 😱。extends 让 Rabbit 的 [[Prototype]] 指向了 Animal
校验
Babel 编译
之前已经对 ES5 中继承 有了深入的了解,Typescript、ES6 的代码会被编译成什么样子呢?可以在 Babel 官网的Try it out页面查看
es6
编译后
_classCallCheck 的作用是检查 Person 是否是通过 new 的方式调用,类必须使用 new 调用,否则会报错。当使用 var person = Person() 的形式调用的时候,this 指向 window,所以 instance instanceof Constructor 就会为 false
这也片面的说明 class 不仅仅是 原型继承的语法糖
es6
编译后
es6
编译后
_inherits
Object.create() 的第二个参数表示要添加到新创建对象的属性
_possibleConstructorReturn
为啥要判断 parent return 呢? 因为 在 constructor 函数中可以 return 例如:
总体实现
首先执行 _inherits(Child, Parent),建立 Child 和 Parent 的原型链关系,即 Object.setPrototypeOf(Child.prototype, Parent.prototype) 和 Object.setPrototypeOf(Child, Parent)
然后调用 Parent.call(this, name),根据 Parent 构造函数的返回值类型确定子类构造函数 this 的初始值 _this
最终,根据子类构造函数,修改 _this 的值,然后返回该值
references
The text was updated successfully, but these errors were encountered: