1.new的作用:
1.创建空对象
2.将空对象的__proto__指向构造函数的prototype
3.将构造函数中的this指向实例对象(即创建出来的空对象)
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
2.实现继承的方式:
使用原型实现继承
将子构造器的原型对象指向父构造器的原型
即 子构造函数.prototype = 父构造函数.prototype;
问题:只能继承父构造器原型对象的上的属性和方法,不能继承父构造函数的实例对象上的属性和方法,同时,父构造函数的原型对象和子构造函数的原型对象上的方法和属性是共享的
// 创建父构造函数 function Parent() {} Parent.prototype.age=25; Parent.prototype,friends=["小明","小丽"]; Parent.prototype.showAge=function(){ console.log(this.age); }; // 创建子构造函数 function Child() {} // 将子构造函数的原型对象指向父构造函数的原型对象来实现继承 Child.prototype=Parent.prototype; // 因为子构造函数的原型被覆盖了,所以现在子构造函数的原型的构造器不再指向Child, // 而指向Parent,创建的Child没有意义,向Child的原型中添加方法会影响到Parent中的原型方法 Child.prototype.say=function(){ console.log(123); } // Parent.prototype.constructor=Child; console.log(Child.prototype); var c1=new Child(); c1.say(); var p1=new Parent(); p1.say();// console.log(Parent.prototype);//父构造函数的原型中也添加了say方法
使用原型链实现继承:
是将子构造器的原型对象指向父构造器的实例对象,
即 Child.prototype=new Parent();
将父类的实例作为子类的原型:
缺点:1.新实例无法向父类构造参数传参
2.继承单一(单继承:只能继承一个父类)
3.所有的新实例都会共享父类实例的方法和属性,(修改一个,另一个也会变)
使用构造函数实现继承:
改变父类构造函数中的this指向,
可以传参,可实现多继承
缺点:子类无法继承父类原型上的对象,只复制父类的实例属性给子类
function Parent(xxx){this.xxx = xxx} Parent.prototype.test = function(){}; function Child(xxx,yyy){ Parent.call(this, xxx); } var child = new Child('a', 'b'); //child.xxx为'a', 但child没有test()
组合继承:
改变父类构造函数中的this指向,创建一个父类原型的对象将其赋给子类的原型对象
- 缺点:通过将子构造函数的原型指向父构造函数的实例,会两次调用子构造函数;
3.手写call,apply,bind 函数改变this指向
call,apply为立即执行函数,apply里面的第二个参数为数组
// 手写call
function test(a, b) {
console.log(this);
return a + b;
}
// // 会有命名重复问题,用symbol解决
// Function.prototype.mycall=function(ctx,...args){
// // var that=this;
// ctx.fn=this;
// var res=ctx.fn(...args);
// delete ctx.fn;
// return res;
// }
// console.log(test.mycall({nam:123},1,2));
Function.prototype.mycall = function (ctx, ...args) {
// globalThis包含全局的this值,类似于全局对象(Global object)
ctx = (ctx === null || ctx === undefined) ? globalThis : Object(ctx);
var key = Symbol("temp");
// Object.defineProperty()对象定义属性
Object.defineProperty(ctx, key, {
value: this,
})
var result = ctx[key](...args);
delete ctx[key];
return result;
}
console.log(test.mycall({ nam: 123 }, 1, 2));
// apply
function test1([a, b]) {
console.log(this);
return a + b;
}
Function.prototype.myapply = function (obj, arr) {
obj = (obj === null || undefined) ? globalThis : Object(obj);
var key = Symbol("temp");
obj.key = this;
var result = obj.key(arr);
delete obj.key;
return result;
}
// console.log(test1.myapply({ nam: 123 }, [1, 2]));
test1.myapply({ nam: 123 }, [1, 2]);
// bind不会立即调用
function test2(a, b) {
console.log(this, a, b);
return a + b;
}
Function.prototype.mybind = function (obj, ...args) {
obj = (obj === null || undefined) ? globalThis : Object(obj);
var key = Symbol("temp");
var that = this;
return function () {
obj.key = that;
var res = obj.key(...args);
delete obj.key;
return res;
}
}
console.log(test2.mybind({ age: 12324235 }, 1, 3)());