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
functionParent(name){this.name=name;}Parent.prototype.getName=function(){returnthis.name;};functionChild(name,age){Parent.call(this,name);this.age=age;}Child.prototype=Object.create(Parent.prototype);Child.prototype.constructor=Child;Child.prototype.getMsg=function(){return`My name is ${this.name}, ${this.age} years old.`;};
ES6:
classParent{constructor(name){this.name=name;}getName(){returnthis.name;}}classChildextendsParent{constructor(name,age){super(name);this.age=age;}getMsg(){return`My name is ${this.name}, ${this.age} years old.`;}}
classParent{constructor(opt){this.name=opt.name;}getName(){returnthis.name;}}classChildextendsParent{constructor(opt){super(opt);this.age=opt.age;}getAge(){returnthis.age+" years old.";};}constme=newChild({name: "Yang",age: 28});
开始模拟实现:
function_extends(child,parent){constprototype=Object.create(parent.prototype);child.prototype=prototype;child.prototype.constructor=child;}function_classCallCheck(instance,Constructor){if(!(instanceinstanceofConstructor)){thrownewTypeError("Cannot call a class as a function");}}varParent=(function(){functionParent(opt){_classCallCheck(this,Parent);this.name=opt.name;}Parent.prototype.getName=functiongetName(){returnthis.name;};returnParent;})();varChild=(function(_Parent){_extends(Child,_Parent);functionChild(opt){_classCallCheck(this,Child);// Constrctor => _Parent.call(this, opt)var_this=(_Parent!=null&&_Parent.call(this,opt))||this;_this.age=opt.age;return_this;}Child.prototype.getAge=functiongetAge(){returnthis.age+" years old.";};returnChild;})(Parent);constmyself=newChild({name: "YyY",age: 18});
写一个 type 函数能检测各种类型的值,如果是基本类型,就使用 typeof,引用类型就使用 toString。
此外鉴于 typeof 的结果是小写,我也希望所有的结果都是小写。
varclass2type={};// 如:[object Array]: "array""Boolean Number String Function Array Date RegExp Object Error Null Undefined Symbol Set Map BigInt".split(" ").map(function(item){class2type["[object "+item+"]"]=item.toLowerCase();});functiontype(obj){if(obj==null){returnobj+"";// IE6}returntypeofobj==="object"||typeofobj==="function"
? class2type[Object.prototype.toString.call(obj)]
: typeofobj;}functionisFunction(obj){returntype(obj)==="function";}varisArray=Array.isArray||function(obj){returntype(obj)==="array";};
前言
主要有:new、Object.create()、Object.setPrototypeOf()、instanceof、class、type API、原型链继承等。
new 实现
我们看下 new 做了什么:
ES6:
Object.create 实现
Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的
__proto__
。使用 Object.create
模拟 Object.create 实现原理
采用了原型式继承:将传入的对象作为创建的对象的原型。
详细 Polyfill,见 MDN:Object.create(),其实就多了参数的判断等信息。
Object.setPrototypeOf 实现
Object.setPrototypeOf() 方法设置一个指定的对象的原型 ( 即, 内部
[[Prototype]]
属性)到另一个对象或null
。注意:由于性能问题,你应该使用 Object.create() 来创建带有你想要的
[[Prototype]]
的新对象。详情见:MDN。使用较旧的
Object.prototype.__proto__
属性,我们可以很容易地定义setPrototypeOf
:instanceof 实现
用法:
instanceof
运算符用于检测构造函数的prototype
属性是否出现在某个实例对象的原型链上。原理:其实就是沿着原型链一直询问,直到
__proto__
为null
为止。注意:
Object.prototype.isPrototypeOf()
用于测试一个对象是否存在于另一个对象的原型链上。isPrototypeOf()
与instanceof
运算符不同。在表达式 "object instanceof AFunction
"中,object 的原型链是针对AFunction.prototype
进行检查的,而不是针对AFunction
本身。如果你有段代码只在需要操作继承自一个特定的原型链的对象的情况下执行,同
instanceof
操作符一样isPrototypeOf()
方法就会派上用场:要检测对象不是某个构造函数的实例时,你可以这样做:
instanceof 模拟实现:主要是沿着
__proto__
判断:L.__proto__
是否等于R.prototype
:原型链继承实现
用法
ES6:
封装继承方法
第一版:
第二版:
第三版:
使用到的几种继承方式
组合式继承:融合原型链继承和构造函数的优点,是 JavaScript 中最常用的继承模式。组合继承最大的缺点是会调用两次父构造函数。
原型式继承:
Object.create
的模拟实现,将传入的对象作为创建的对象的原型。寄生组合式继承:只调用了一次 Parent 构造函数,并且因此避免了在 Parent.prototype 上面创建不必要的、多余的属性。
PS:其他几种继承方式见这里JavaScript 深入之继承的多种方式和优缺点
。
引用《JavaScript 高级程序设计》中对寄生组合式继承的夸赞就是:
这种方式的高效率体现它只调用了一次
Parent
构造函数,并且因此避免了在Parent.prototype
上面创建不必要的、多余的属性。与此同时,原型链还能保持不变;因此,还能够正常使用instanceof
和isPrototypeOf
。开发人员普遍认为寄生组合式继承是引用类型最理想的继承范式。class 实现
主要是模拟使用
extends
,并模拟super
可以给其父构造函数传值,如 Parent 中的 opt:开始模拟实现:
PS:使用 Babel 编译器编译如上代码,完整版在这里。
Array.isArray 实现
可以通过 toString() 来获取每个对象的类型。为了每个对象都能通过
Object.prototype.toString()
来检测,需要以Function.prototype.call()
或者Function.prototype.apply()
的形式来调用,传递要检查的对象作为第一个参数。type API 实现
写一个 type 函数能检测各种类型的值,如果是基本类型,就使用
typeof
,引用类型就使用toString
。此外鉴于
typeof
的结果是小写,我也希望所有的结果都是小写。参考资料:JavaScript 专题之类型判断(上)
参考资料
The text was updated successfully, but these errors were encountered: