1.
function Person () {
this.age = 10; //构造函数实例属性
}
Person.prototype.age =15
Person.prototype.myname ='XXX'
Person.age = 5; //构造函数自有属性
function Animals () {
this.age =15; //构造函数实例属性
Person.call(this);//1.Person执行 2.this指向改变 3.参数有序传入
}
let p1 = new Animals() //实例化构造函数
console.log(p1.age,p1.myname) //实例对象属性 打印10,XXX,函数实例化后如果存在实例对象属性,则取实例对象属性,不存在则取其原型属性
let p2 = {age : 20}
Person.call(p2)
let p3 = new Person()
console.log(p3.age) //打印20,this指向p2,如果call里面为函数,即使函数内有this.age,没有实例化之前是找不到函数的age的
2.call,apply, bind源码
call: (字符串传递参数)
Function.prototype.luckycall = function (ctx,...arr) {
ctx.fn = this //给ctx一个属性,把调用的函数内容给这个属性
ctx.fn(...arr) //调用这个函数
delete ctx.fn
}
apply: (数组传递参数)
Function.prototype.luckyapply = function (ctx,arr) {
ctx.fn = this //给ctx一个属性,把调用的函数内容给这个属性
ctx.fn(...arr) //调用这个函数
delete ctx.fn
}
bind:(字符串传递参数,返回一个函数)
Function.prototype.luckyapply = function (ctx,arr) {
let that = this
let arg = [...arr] //把一堆参数放入数组,满足apply要求
return function() {
that.apply(ctx,arg) //返回该函数调用apply方法的函数
}
}
具体到Function.prototype
,就是所有函数的原型,因为通常函数都可以认为是通过new Function制造出来的。换句话说,Function.prototype
上面承载了用于继承给所有函数的那些属性,例如:call、bind、apply等。
3.原型链
原型链继承:把A构造函数的实例化放到另一个B构造函数的原型上,B继承了A,实例化B,B可以拿到A所有属性。缺点:引用类型值会共享。
(1)值类型:数值、布尔值、null、undefined。
(2)引用类型:对象、数组、函数。
构造函数继承,使用call(this)继承,解决了实例属性相互影响问题。缺点:无法继承方法
组合继承:组合原型链继承和构造函数继承,优势互补