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
"use strict";/** * Symbol.hasInstance 属性,指向一个内部方法。 * 当其它对象使用 instanceof 运算符,判断是否为该对象的实例时,会调用这个方法。 * 比如,foo instanceof Foo 在语言内部,实际调用的是Foo[Symbol.hasInstance](foo)。 */function_instanceof(left,right){if(right!=null&&typeofSymbol!=="undefined"&&right[Symbol.hasInstance]){return!!right[Symbol.hasInstance](left);}else{returnleftinstanceofright;}}// 防止直接当方法调用function_classCallCheck(instance,Constructor){// 判断 instance 是否为 Constructor 的实例if(!_instanceof(instance,Constructor)){thrownewTypeError("Cannot call a class as a function");}}/** * * Object.defineProperty 直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。 * */function_defineProperties(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);}}function_createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);// 静态方法直接放在构造函数上if(staticProps)_defineProperties(Constructor,staticProps);returnConstructor;}varFruit=/*#__PURE__*/(function(){functionFruit(name){_classCallCheck(this,Fruit);this.name=name;}_createClass(Fruit,[{key: "showName",value: functionshowName(){console.info("Fruit Name:",this.name);}}]);returnFruit;})();
在上面转译的代码中,处理的主要思路有:
_classCallCheck 方法判断调用的方式,防止 Fruit() 这样直接调用。
_createClass 方法在 prototype 上添加公用方法,在 Fruit 上添加静态方法。
这种方式跟组合使用构造函数模式和原型模式创建对象很相似,不过表达的语义不太一样。
再来看下继承转译后的代码:
"use strict";function_typeof(obj){if(typeofSymbol==="function"&&typeofSymbol.iterator==="symbol"){_typeof=function_typeof(obj){returntypeofobj;};}else{_typeof=function_typeof(obj){returnobj&&typeofSymbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype
? "symbol"
: typeofobj;};}return_typeof(obj);}function_possibleConstructorReturn(self,call){if(call&&(_typeof(call)==="object"||typeofcall==="function")){returncall;}return_assertThisInitialized(self);}function_assertThisInitialized(self){if(self===void0){thrownewReferenceError("this hasn't been initialised - super() hasn't been called");}returnself;}// 获取对象原型function_getPrototypeOf(o){_getPrototypeOf=Object.setPrototypeOf
? Object.getPrototypeOf
: function_getPrototypeOf(o){returno.__proto__||Object.getPrototypeOf(o);};return_getPrototypeOf(o);}/** * * Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。 * @param {*} superClass */function_inherits(subClass,superClass){if(typeofsuperClass!=="function"&&superClass!==null){thrownewTypeError("Super expression must either be null or a function");}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor: {value: subClass,writable: true,configurable: true}});// 没有这一步的话,就拿不到父类的属性if(superClass)_setPrototypeOf(subClass,superClass);}// 设置对象原型function_setPrototypeOf(o,p){_setPrototypeOf=Object.setPrototypeOf||function_setPrototypeOf(o,p){o.__proto__=p;returno;};return_setPrototypeOf(o,p);}function_instanceof(left,right){if(right!=null&&typeofSymbol!=="undefined"&&right[Symbol.hasInstance]){return!!right[Symbol.hasInstance](left);}else{returnleftinstanceofright;}}function_classCallCheck(instance,Constructor){if(!_instanceof(instance,Constructor)){thrownewTypeError("Cannot call a class as a function");}}function_defineProperties(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);}}function_createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);returnConstructor;}varFruit=/*#__PURE__*/(function(){functionFruit(name){_classCallCheck(this,Fruit);this.name=name;}_createClass(Fruit,[{key: "showName",value: functionshowName(){console.info("Fruit Name:",this.name);}}]);returnFruit;})();varApple=/*#__PURE__*/(function(_Fruit){_inherits(Apple,_Fruit);functionApple(name,color){var_this;_classCallCheck(this,Apple);// _getPrototypeOf(Apple).call(this, name) 调用的实际是父类的函数,注意没有使用 new ,返回的是默认的 undefined_this=_possibleConstructorReturn(this,_getPrototypeOf(Apple).call(this,name));_this.color=color;return_this;}_createClass(Apple,[{key: "showColor",value: functionshowColor(){console.info("Apple Color:",this.color);}}]);returnApple;})(Fruit);letapple=newApple("apple","green");console.info("apple:",apple);apple.showName();apple.showColor();
class 继承通过 extends 实现。继承时,类中构造函数必须要执行 super 方法,否则创建实例的时候会报错。
classA{}classBextendsA{constructor(){}}letobj=newB();// VM55958:3 Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
目录
引子
在一些书籍中花费了不少的篇幅进行讲述,新的语法中也出现了相关的关键字,实现的方式中也涉及到 JavaScript 中很重要的知识点。
注意:JavaScript 中并没有类似 Java 中的类和继承,以下用“类”和“继承”是为了方便描述。
上一篇 JavaScript 新旧替换三:参数转换。
ES5 方式
实现继承功能的方式有多种,JavaScript 中常用的继承模式是组合继承,这里以此为例。
在组合继承中,主要的思路是:
Fruit.call(this, name)
绑定子类的this
,达到继承父类属性效果。prototype
属性,子类的实例会沿着原型链查找,达到了继承父类方法的效果。ES2015+ 方式
用新的语法实现上面的继承:
在书写形式上有很大的变化,但实际上也是通过原型链实现,通过 Babel 转译为 ES5 看下是怎样的实现思路。
首先说明一下 Babel 中转译有两种模式:normal 和 loose。
选择 normal 模式的转译更加合适,先来看下
Fruit
类转译后的实现:在上面转译的代码中,处理的主要思路有:
_classCallCheck
方法判断调用的方式,防止Fruit()
这样直接调用。_createClass
方法在prototype
上添加公用方法,在Fruit
上添加静态方法。这种方式跟组合使用构造函数模式和原型模式创建对象很相似,不过表达的语义不太一样。
再来看下继承转译后的代码:
在上面转译的代码中,处理的主要思路是:
_inherits
方法基于父类的prototype
创建了一个新的对象,赋给了子类的prototype
。还将子类的__proto__
指向了父类,为的是继承父类的属性。prototype
上定义子类自己的方法。this
的值。ES2015+ 方式语法点
class
ES2015 引入了类的概念,通过
class
关键字可以定义类。类有下面一些特点:new
调用,否则会报错。static
关键字。this
指向类的实例。constructor
constructor
是构造方法,通过new
命令生成对象实例时,自动调用该方法。一个类必须有constructor
方法,如果没有显式定义,一个空的constructor
方法会被默认添加。extends
class
继承通过extends
实现。继承时,类中构造函数必须要执行super
方法,否则创建实例的时候会报错。子类中如果没有显式的写出构造方法,会默认的添加。
super
super
关键字可以当做函数或对象使用。使用super
的时候,必须显式指定是作为函数、还是作为对象使用,否则会报错。函数使用
对象使用
参考资料
🗑️
最近去找了奥斯卡每届的最佳影片资料,又去看了下美版的《无间道风云》。表达的方式很不一样,可能是由于文化之间的差异。虽然有差异,但个人感觉最终突出的主题是一样的:出来混,迟早是要还的。
The text was updated successfully, but these errors were encountered: