- prototype 与 _proto_
//实现一个instanceof
function instance_of(L,R){
L = L.__proto__;
while(L !== null){
if(L === R.prototype) return true;
L = L.__proto__;
}
return false;
}
参考文章:原型链—Object\Function _proto_ 的关系
参考文章:JavaScript 世界万物诞生记
- new的实现
重点是两步:
1、实例的__proto__指向构造函数的prototype
2、构造函数中的this指向实例。
//var p = mockNew(Person,"olivia",18);
function Person(name, age) {
this.name = name;
this.age = age;
}
function mockNew(){
//1、创建一个对象
let obj = {};
//arguments 是类数组,不是真正的数组,所以不能直接调用shif方法。也可用Array.from转换为数组,详见mockNew2
//获取construtor,即构造函数Person
let _constructor = [].shift.call(arguments);
//2、将对象的_proto_ 指向构造函数的原型对象
obj.__proto__ = _constructor.prototype;
//3、将构造函数(Person)中的this 指向obj
_constructor.apply(obj,arguments);
//4、返回这个函数
return obj;
}
function mockNew2(){
//1、创建一个对象
let obj = {};
//arguments 是类数组,不是真正的数组,使用用Array.from转换为数组
//获取construtor,即构造函数Person
let arr = [];
arr = Array.from(arguments);
let _constructor = arr.shift();
//2、将对象的_proto_ 指向构造函数的原型对象
obj.__proto__ = _constructor.prototype;
//3、将构造函数(Person)中的this 指向obj
_constructor.apply(obj,arr);
//4、返回这个函数
return obj;
}
//自己实现的组合寄生继承
//重点在两句:
//1、在子构造函数中使用apply,调用父构造函数
//2、子构造函数的prototype = Object.create(父构造函数的prototype)
//最后记得将子类的constructor指回来
function Parent(name){
this.name = "name";
}
Parent.prototype.callName = function(){
console.log(this.name)
}
function Child(name){
//*****重点1*****
Parent.apply(this,arguments);
this.name = name;
}
//*****重点2*****
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
//别人的实现
//作者:寻找海蓝96
//链接:https://juejin.im/post/5d51e16d6fb9a06ae17d6bbc
function Parent(name) {
this.parent = name
}
Parent.prototype.say = function() {
console.log(`${this.parent}: 你打篮球的样子像kunkun`)
}
function Child(name, parent) {
// 将父类的构造函数绑定在子类上
Parent.call(this, parent)
this.child = name
}
/**
1. 这一步不用Child.prototype =Parent.prototype的原因是怕共享内存,修改父类原型对象就会影响子类
2. 不用Child.prototype = new Parent()的原因是会调用2次父类的构造方法(另一次是call),会存在一份多余的父类实例属性
3. Object.create是创建了父类原型的副本,与父类原型完全隔离
*/
Child.prototype = Object.create(Parent.prototype);
Child.prototype.say = function() {
console.log(`${this.parent}好,我是练习时长两年半的${this.child}`);
}
// 注意记得把子类的构造指向子类本身
Child.prototype.constructor = Child;
var parent = new Parent('father');
parent.say() // father: 你打篮球的样子像kunkun
var child = new Child('cxk', 'father');
child.say() // father好,我是练习时长两年半的cxk