call、apply、bind

众所周知 call、apply、bind 的作用都是‘改变’作用域,但是网上对这这‘改变’说得含糊其辞,并未做详细说明,‘改变’是直接替换作用域?谁替换谁?怎么产生效果?这些问题如果不理解清楚,就算看过手写实现,估计也记不长久,基于此,这里做简单记录,以免时间过长遗忘,方便回顾。

call

使用 call() 方法,您可以编写能够在不同对象上使用的方法。
函数是对象方法
在 JavaScript 中,函数是对象的方法。
如果一个函数不是 JavaScript 对象的方法,那么它就是全局对象的函数(参见前一章)。
下面的例子创建了带有三个属性的对象(firstName、lastName、fullName)。

举个栗子

var person = {
    firstName:"Bill",
    lastName: "Gates",
    fullName: function () {
        return this.firstName + " " + this.lastName;
    }
}
person.fullName();		// 将返回 "Bill Gates"

fullName 属性是一个方法。person 对象是该方法的拥有者。

fullName 属性属于 person 对象的方法

JavaScript call() 方法

call() 方法是预定义的 JavaScript 方法。

它可以用来调用所有者对象作为参数的方法。

通过 call(),您能够使用属于另一个对象的方法。

本例调用 person 的 fullName 方法,并用于 person1:

再举个栗子

var person = {
    fullName: function() {
        return this.firstName + " " + this.lastName;
    }
}
var person1 = {
    firstName:"Bill",
    lastName: "Gates",
}
var person2 = {
    firstName:"Steve",
    lastName: "Jobs",
}
person.fullName.call(person1);  // 将返回 "Bill Gates"

下边调用 person 的 fullName 方法,并用于 person2:

var person = {
    fullName: function() {
        return this.firstName + " " + this.lastName;
    }
}
var person1 = {
    firstName:"John",
    lastName: "Doe",
}
var person2 = {
    firstName:"Mary",
    lastName: "Doe",
}
person.fullName.call(person2);  // 将返回 "Steve Jobs"

带参数的 call() 方法
call() 方法可接受参数:

var person = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + "," + city + "," + country;
  }
}
var person1 = {
  firstName:"Bill",
  lastName: "Gates"
}
person.fullName.call(person1, "Seattle", "USA");

apply

JavaScript apply() 方法
apply() 方法与 call() 方法非常相似:
在下边代码中,person 的 fullName 方法被应用到 person1:

var person = {
    fullName: function() {
        return this.firstName + " " + this.lastName;
    }
}
var person1 = {
    firstName: "Bill",
    lastName: "Gates",
}
person.fullName.apply(person1);  // 将返回 "Bill Gates"

call() 和 apply() 之间的区别
不同之处是:

call() 方法分别接受参数。

apply() 方法接受数组形式的参数。

如果要使用数组而不是参数列表,则 apply() 方法非常方便。

带参数的 apply() 方法
apply() 方法接受数组中的参数

举栗

var person = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + "," + city + "," + country;
  }
}
var person1 = {
  firstName:"John",
  lastName: "Doe"
}
person.fullName.apply(person1, ["Oslo", "Norway"]);

与 call() 方法对比:

var person = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + "," + city + "," + country;
  }
}
var person1 = {
  firstName:"John",
  lastName: "Doe"
}
person.fullName.call(person1, "Oslo", "Norway");

bind

bind() 方法会创建一个新函数,当这个新函数被调用时,它的 this 值是传递给 bind() 的第一个参数, 它的参数是 bind() 的其他参数和其原本的参数。
语法

fun.bind(thisArg[, arg1[, arg2[, ...]]])

thisArg 当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。当使用 new 操作符调用绑定函数时,该参数无效。

arg1, arg2, … (可选)当绑定函数被调用时,这些参数加上绑定函数本身的参数会按照顺序作为原函数运行时的参数
参数
bind 的第一个参数会作为原函数运行时的 this 指向,不多说;而第二个开始的参数是可选的,当绑定函数被调用时,这些参数加上绑定函数本身的参数会按照顺序作为原函数运行时的参数。怎么理解?

function fn(a, b, c) {
  return a + b + c;
}

var _fn = fn.bind(null, 10);
var ans = _fn(20, 30); // 60

fn 函数需要三个参数,_fn 函数将 10 作为默认的第一个参数,所以只需要传入两个参数即可,如果你不小心传入了三个参数,放心,也只会取前两个。

function fn(a, b, c) {
  return a + b + c;
}

var _fn = fn.bind(null, 10);
var ans = _fn(20, 30, 40); // 60

这有啥用呢?如果某些函数,前几个参数已经 “内定” 了,我们便可以用 bind 返回一个新的函数。也就是说,bind() 能使一个函数拥有预设的初始参数。这些参数(如果有的话)作为 bind() 的第二个参数跟在 this 后面,之后它们会被插入到目标函数的参数列表的开始位置,传递给绑定函数的参数会跟在它们的后面。

function list() {
  return Array.prototype.slice.call(arguments);
}

var list1 = list(1, 2, 3); // [1, 2, 3]

// Create a function with a preset leading argument
var leadingThirtysevenList = list.bind(undefined, 37);

var list2 = leadingThirtysevenList(); // [37]
var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值