一、概念
call 方法:指定函数内部 this 的指向,然后在指定的作用域中,调用该函数。假设参数为空、null 或者undefined,非严格模式下,this 默认指向全局对象;而严格模式下,this 的值为 undefined;如果第一个参数为原始值,会被包装成对象。
apply 方法: apply 方法的作用与 call 方法类似,也是改变 this 指向,然后再调用该函数。唯一的区别就是:它接收一个数组作为函数执行时的参数。第一个参数为 null 、undefined 或者原始值时,结果和 call 方法一致。
bind 方法: 用于将函数体内的 this 绑定到某个对象,然后返回一个新函数,不论怎么调用,这个函数都有同样的 this 值。 第一个参数设为 null 或者 undefined 时,this 指向和 call 方法一致。
二、 call 方法的例子
- 如果 call 方法的参数为空、null 或者 undefined,this 默认指向全局对象。
var n = 123;
var obj = { n: 456 };
function a() {
console.log(this.n);
}
a.call()
a.call(null)
a.call(undefined)
a.call(window)
a.call(obj)
- 如果 call 方法的第一个参数为原始值,会被包装成对象,再传入 call 方法。
var f = function () {
return this;
};
f.call(5)
var obj = {};
obj.hasOwnProperty('toString')
obj.hasOwnProperty = function () {
return true;
};
obj.hasOwnProperty('toString')
Object.prototype.hasOwnProperty.call(obj, 'toString')
var animals = [
{ species: 'Lion', name: 'King' },
{ species: 'Whale', name: 'Fail' }];
for (var i = 0; i < animals.length; i++) {
(function(i) {
this.print = function() {
console.log('#' + i + ' ' + this.species
+ ': ' + this.name);
}
this.print();
}).call(animals[i], i);}
- 使用 call 方法调用函数且不指定第一个参数。非严格模式下,this 指向全局对象;严格模式下,this 的值是 undefined。
(1)示例一
var sData = 'Wisen';
function display() {
console.log('sData value is %s ', this.sData);
}
display.call();
(2)示例2
'use strict';
var sData = 'Wisen';
function display() {
console.log('sData value is %s ', this.sData);
}
display.call();
三、apply 方法的例子
var a = [10, 2, 4, 15, 9];
Math.max.apply(null, a)
- 使用 apply 方法将数组的空元素变为 undefined( 遍历时,数组的 forEach 方法会跳过空元素)
var a = ['a', , 'b'];
function print(i) {
console.log(i);
}
a.forEach(print)
Array.apply(null, a).forEach(print)
- 使用 apply 方法转换类似数组的对象(伪数组,必须有 length 属性)
Array.prototype.slice.apply({0: 1, length: 1})
Array.prototype.slice.apply({0: 1, length: 2})
Array.prototype.slice.apply({length: 1})
var array = ['a', 'b'];var elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array);
四、bind 方法的例子
element.addEventListener('click', o.m.bind(o));
var listener = o.m.bind(o);
element.addEventListener('click', listener);
element.removeEventListener('click', listener);
function list() {
return Array.prototype.slice.call(arguments);}
function addArguments(arg1, arg2) {
return arg1 + arg2
}
var list1 = list(1, 2, 3);
var result1 = addArguments(1, 2);
var leadingThirtysevenList = list.bind(null, 37);
var addThirtySeven = addArguments.bind(null, 37);
var list2 = leadingThirtysevenList();
var list3 = leadingThirtysevenList(1, 2, 3);
var result2 = addThirtySeven(5);
var result3 = addThirtySeven(5, 10);
- bind 方法结合 call()、apply() 使用
(1)示例一
[1, 2, 3].slice(0, 1)
Array.prototype.slice.call([1, 2, 3], 0, 1)
(2)示例二
var slice = Function.prototype.call.bind(Array.prototype.slice);
slice([1, 2, 3], 0, 1)
(3)示例三
var push = Function.prototype.call.bind(Array.prototype.push);
var pop = Function.prototype.call.bind(Array.prototype.pop);
var a = [1 ,2 ,3];
push(a, 4)
a
pop(a)
a
(4)示例四
function f() {
console.log(this.v);
}
var o = { v: 123 };
var bind = Function.prototype.call.bind(Function.prototype.bind);
bind(f, o)()
(5)示例五
var slice = Array.prototype.slice;
slice.apply(arguments);
-----------------------------------------------------------------
var slice = Function.prototype.apply.bind(Array.prototype.slice);
slice(arguments);