JavaScript中的call(), apply()和bind()是Function.prototype下的方法,都是用于改变函数运行时上下文,最终的返回值是你调用的方法的返回值,若该方法没有返回值,则返回undefined。这几个方法很好地体现了js函数式语言特性,在js中几乎每一次编写函数式语言风格的代码,都离不开call和apply。
1. call()
-
描述:
call()
方法使用一个指定的this
值和单独给出的一个或多个参数来调用一个函数。
call()
允许为不同的对象分配和调用属于一个对象的函数/方法。
call()
提供新的 this 值给当前调用的函数/方法。你可以使用 call 来实现继承:写一个方法,然后让另外一个新的对象来继承它(而不是在新对象中再写一次这个方法)。 - 语法:
function.call(thisArg, arg1, arg2, ...)
-
参数:
thisArg
在function
函数运行时指定的this
值。需要注意的是,指定的this
值并不一定是该函数执行时真正的this
值,如果这个函数在[非严格模式
]下运行,则指定为null
和undefined
的this
值会自动指向全局对象(浏览器中就是 window 对象),同时值为原始值(数字,字符串,布尔值)的this
会指向该原始值的自动包装对象。
arg1, arg2, ...
指定的参数列表。 -
返回值:
使用调用者提供的 this 值和参数调用该函数的返回值。若该方法没有返回值,则返回 undefined。 - 示例:
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
console.log(new Food('cheese', 5).name);
// expected output: "cheese"
2. apply()
-
描述
apply()
方法调用一个具有给定this
值的函数,以及作为一个数组(或类似数组对象)提供的参数。
在调用一个存在的函数时,你可以为其制定一个this
对象,this
指当前对象,也就是正在调用这个函数的对象。使用apply
,你可以只写一次这个方法然后在另一个对象中继承它,而不用在新对象中重复写该方法。
apply
与call()
非常相似,不同之处在于提供参数的方式。apply
使用参数数组而不是一组参数列表。apply
可以使用数组字面量(array literal),如fun.apply(this, ['eat', 'bananas'])
,或数组对象, 如fun.apply(this, new Array('eat', 'bananas'))
。
你也可以使用arguments
对象作为argsArray
参数。arguments
是一个函数的局部变量。 它可以被用作被调用对象的所有未指定的参数。 这样,你在使用apply函数的时候就不需要知道被调用对象的所有参数。 你可以使用arguments来把所有的参数传递给被调用对象。 被调用对象接下来就负责处理这些参数。
从 ECMAScript 第5版开始,可以使用任何种类的类数组对象,就是说只要有一个length
属性和(0..length-1)
范围的整数属性。例如现在可以使用NodeList
或一个自己定义的类似{'length': 2, '0': 'eat', '1': 'bananas'}
形式的对象。
需要注意:Chrome 14 以及 Internet Explorer 9 仍然不接受类数组对象。如果传入类数组对象,它们会抛出异常。
- 语法
function.apply(thisArg, [argsArray])
-
参数
thisArg
可选的。在function
函数运行时使用的this
值。请注意,this
可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为null
或undefined
时会自动替换为指向全局对象,原始值会被包装。
argsArray
可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给function
函数。如果改参数的值为null
或undefined
,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。 -
返回值
调用有指定this
值和参数的函数的结果。 - 示例
var numbers = [5, 6, 2, 3, 7];
var max = Math.max.apply(null, numbers);
console.log(max);
// expected output: 7
var min = Math.min.apply(null, numbers);
console.log(min);
// expected output: 2
3. bind()
-
描述
bind()
方法创建一个新的函数,在调用时设置this关键字为提供的值。并在调用新函数时,将给定参数列表作为原函数的参数序列的前若干项。
bind()
函数会创建一个新绑定函数(bound function,BF)
。绑定函数是一个exotic function object
(怪异函数对象,ECMAScript 2015中的术语),它包装了原函数对象。调用绑定函数
通常会导致执行包装函数
。
绑定函数
具有以下内部属性:
[[BoundTargetFunction]]
- 包装的函数对象
[[BoundThis]]
- 在调用包装函数时始终作为this
值传递的值。
[[BoundArguments]]
- 列表,在对包装函数做任何调用都会优先用列表元素填充参数列表。
[[Call]]
- 执行与此对象关联的代码。通过函数调用表达式调用。内部方法的参数是一个this值和一个包含通过调用表达式传递给函数的参数的列表。
当调用绑定函数时,它调用[[BoundTargetFunction]]
上的内部方法[[Call]]
,就像这样Call(boundThis, args)
。其中,boundThis
是[[BoundThis]]
,args
是[[BoundArguments]]
加上通过函数调用传入的参数列表。
绑定函数也可以使用new
运算符构造,它会表现为目标函数已经被构建完毕了似的。提供的this
值会被忽略,但前置参数仍会提供给模拟函数。 - 语法
function.bind(thisArg[, arg1[, arg2[, ...]]])
-
参数
thisArg
调用绑定函数时作为this
参数传递给目标函数的值。 如果使用new
运算符构造绑定函数,则忽略该值。当使用bind
在setTimeout
中创建一个函数(作为回调提供)时,作为thisArg
传递的任何原始值都将转换为object
。如果bind
函数的参数列表为空,执行作用域的this
将被视为新函数的thisArg
。
arg1, arg2, ...
当目标函数被调用时,预先添加到绑定函数的参数列表中的参数。 -
返回值
返回一个原函数的拷贝,并拥有指定的this
值和初始参数。 - 示例
var module = {
x: 42,
getX: function() {
return this.x;
}
}
var unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined
var boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42
网友评论