日常笔记
call和apply
call和apply的作用就是改变this的指向,区别就是传参列表不同
call和apply可以理解为用别人的函数实现自己的需求,call必须符合调用的函数的形参,不可删除形参
function a(){
}
a.call() = a()
call和apply更多用于组装函数 由我来组成头部
call是把实参按照形参的个数传入,apply则是需要传入一个数组arguments
call是按照形参个数传实参
function Wheel(Wheelsize,style){
this.wheelsize = Wheelsize;
this.style = style
}
function Sit(sitColor){
this.sitColor = sitColor;
}
function Model(width,height,len){
this.width = width;
this.height = height;
this.len = len;
}
function Car(Wheelsize,style,sitColor,width,height,len){
Wheel.call(this,Wheelsize,style);
Sit.call(this,sitColor);
Model.call(this,width,height,len);
}
var BMW = new Car(100,"幻夜",black,100,100,100);
apply则是需要传入一个数组arguments
function Wheel(Wheelsize,style){
this.wheelsize = Wheelsize;
this.style = style
}
function Sit(sitColor){
this.sitColor = sitColor;
}
function Model(width,height,len){
this.width = width;
this.height = height;
this.len = len;
}
function Car(Wheelsize,style,sitColor,width,height,len){
Wheel.call(this,[Wheelsize,style]);
Sit.call(this,[sitColor]);
Model.call(this,[width,height,len]);
}
var BMW = new Car(100,"幻夜",black,100,100,100);
bind
bind
和call
还有apply
都是去重新定义this这个对象的。
const name = "小钟",age = 20;
let obj = {
name:"小周",
objAge:this.age,
myFun:function(){
console.log(this.name+"年龄"+this.age);
}
}
const db = {
name:"旭宇",
age:"99"
}
obj.myFun.call(db); //旭宇年龄99
obj.myFun.apply(db); //旭宇年龄99
obj.myFun.bind(db)(); //旭宇年龄99
由上面例子可以看出来,除了调用bind方法后面多了一个()外,结果返回跟apply和call都一致!
由此得出结论,bind
返回的是一个新的函数,必须得调用才会执行
bind()
最简单的用法是创建一个函数,使这个函数不论怎么调用都有同样的this值。常见的错误就像上面的例子一样,将方法从对象中拿出来,然后调用,并且希望this指向原来的对象。如果不做特殊处理,一般会丢失原来的对象。使用bind()
方法能够很漂亮的解决这个问题:
this.num = 9;
var mymodule = {
num: 81,
getNum: function() { return this.num; }
};
module.getNum(); // 81
var getNum = module.getNum;
getNum(); // 9, 因为在这个例子中,"this"指向全局对象
// 创建一个'this'绑定到module的函数
var boundGetNum = getNum.bind(module);
boundGetNum(); // 81
继承模式
公有原型
最基础的继承是这样的,同一个原型被两个函数指向
function Son(){
}
function Father(){
}
Son.prototype = Father.prototype;
var son = new Son;
var father = new Father;
模块化封装起来起来就是:
function Son(){
}
function Father(){
}
function inherit(Target, Origin){
Target.prototype = Origin.prototype;
}
inherit(Son, Father);
var son = new Son;
var father = new Father;
但这个有个不足就是,无法给单个被继承的函数的原型添加属性(因为指向同一个原型,一加属性就一起加)
最终模式——圣杯模式
思路是:建立一个function F()作为中间层,利用原型链的原理
function Son(){
}
function Father(){
}
function inherit(Target, Origin){
function F(){}
F.prototype = Origin.prototype;
Target.prototype = new F(); //把Target函数的原型换成F,但是通过原型链的原理,Target函数的原型最终还是继承于Origin函数的原型,就可以解决公有原型继承的缺点。
Target.prototype.constructor = Target; //构造函数归位
Target.prototype.uber = Origin.prototype //声明超类(超级父级,究竟继承至谁)
//正常超类是写super,但是js里super是保留字,所以这里写uber
}
inherit(Son, Father);
var son = new Son();
var father = new Father();