作用: call,apply,bind可以动态改变传入函数的this
使用: f.call(o,para1,para2…)
f.apply(o,[para1,para2…])
应用:
借用方法
var xm = {
name: '小明',
food: '饺子',
cook: function() {
console.log("我把" + this.food + "做好了");
}
}
var xl = {
name: '小李',
food: '方便面'
}
xm.cook();
xm.cook.call(xl);
xm.cook.apply(xl);
实现继承
function Animal(name) {
this.name = name;
this.showName = function() {
alert(this.name);
}
}
function Cat(name) {
Animal.apply(this, [name]);
//Animal.call(this, name);
}
var cat = new Cat("咕咕");
cat.showName();
区别
call 和 apply 第一个参数都是一样的,这个参数将代表this指向的对象
call 接收的参数 需要 一个个的 枚举出来
apply 接收的参数, 可以直接是一个数组,也可以是类数组对象(arguments)
手写call
let obj1 = {
value: 1
}
let obj2 = {
value: 2,
getValue(name, age) {
return {
value: this.value,
name: name,
age: age
}
}
}
Function.prototype.myCall = function () {
const fn = Symbol('fn') //用symbole声明一个独有的属性,防止覆盖已有属性
let ctx = arguments[0] || window // 如果没有this传入,默认绑定window对象
ctx.fn = this // 函数赋值(改变this执行);可以再次输出this,查看效果
let args = [...arguments].slice(1) // 获取传入的参数。这里为了下面方便判断,所以截去第一个参数(this),并且把剩余参数变为数组;
let result = args.length > 0 ? ctx.fn(...args) : ctx.fn() // 执行当前函数
delete ctx.fn // 删除我们改写的fn属性。因为不能改变原有对象,我们只是改变this,执行完就删除
retun result // 返回结果
}
// 调用
console.log('call方法改写', obj2.myCall(obj1,'小明',12))
步骤分解
语义分解: 上面函数调用call函数,内部代码就变成了这样
1. 会先判断当前是否有this,也就是是否是{}。
2. 声明一个独有的属性,方便调用
3. 改变this指向(函数赋值)
4. 根据当前传入的参数个数,来判断执行函数所带的参数
5. 删除改变的fn属性
6. 返回结果
// 调用前
// let obj1 = {
// value: 1
// }
// 调用后
let obj1 = {
value: 1,
getValue(name, age) {
return {
value: this.value,
name: name,
age: age
}
}
}
++++++++++++++++++++++++++++
let obj2 = {
value: 2,
getValue(name, age) {
return {
value: this.value,
name: name,
age: age
}
}
}
代码分解
1. const fn = Symbol('fn')// Symbol 作为对象的属性名,可以保证属性不重名
2. arguments: 任意一个函数的内部,都有一个arguments对象
arguments作用:获取传递来的所有实参,他是一个类数组,类数组。l
3. 类数组转化为数组的方法 [...argument] Array.from(arguments) Array.prototype.
slice.call(arguments)
手写apply
let obj1 = {
value: 1
}
let obj2 = {
value: 2,
getValue(name, age) {
return {
value: this.value,
name: name,
age: age
}
}
}
Function.prototype.myApply = function () {
const fn = Symbol('fn')
let ctx = arguments[0] || window
ctx.fn = this
let args = [...arguments].slice(1)
let result = args.length > 0 ? ctx.fn(...args) : ctx.fn()
delete ctx.fn
return result
}
// 调用
console.log('call方法改写', obj2.myApplyl(obj1,'小明',12))
bind返回一个新的函数 ,所以需要重新调用一次