本文主要是介绍【JavaScript】this关键字:绑定this的方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 1 Function.prototype.call()
- 2 Function.prototype.apply()
- 3 Function.prototype.bind()
JavaScript 提供了call、apply、bind这三个方法,来切换/固定this的指向。
1 Function.prototype.call()
函数实例的call方法,可以指定函数内部this的指向(即函数执行时所在的作用域),然后在所指定的作用域中,调用该函数。
var obj = {};var f = function () {return this;
};f() === window // true
f.call(obj) === obj // true
call方法的参数,应该是一个对象。如果参数为空、null和undefined,则默认传入全局对象。
var n = 123;
var obj = { n: 456 };function a() {console.log(this.n);
}a.call() // 123
a.call(null) // 123
a.call(undefined) // 123
a.call(window) // 123
a.call(obj) // 456
如果call方法的参数是一个原始值,那么这个原始值会自动转成对应的包装对象,然后传入call方法。
var f = function () {return this;
};f.call(5)
// Number {[[PrimitiveValue]]: 5}
call方法还可以接受多个参数。
func.call(thisValue, arg1, arg2, ...)
call的第一个参数就是this所要指向的那个对象,后面的参数则是函数调用时所需的参数。
function add(a, b) {return a + b;
}add.call(this, 1, 2) // 3
call方法的一个应用是调用对象的原生方法。
var obj = {};
obj.hasOwnProperty('toString') // false// 覆盖掉继承的 hasOwnProperty 方法
obj.hasOwnProperty = function () {return true;
};
obj.hasOwnProperty('toString') // trueObject.prototype.hasOwnProperty.call(obj, 'toString') // false
2 Function.prototype.apply()
apply方法的作用与call方法类似,也是改变this指向,然后再调用该函数。唯一的区别就是,它接收一个数组作为函数执行时的参数,使用格式如下。
func.apply(thisValue, [arg1, arg2, ...])
apply方法的第一个参数也是this所要指向的那个对象,如果设为null或undefined,则等同于指定全局对象。第二个参数则是一个数组,该数组的所有成员依次作为参数,传入原函数。原函数的参数,在call方法中必须一个个添加,但是在apply方法中,必须以数组形式添加。
function f(x, y){console.log(x + y);
}f.call(null, 1, 1) // 2
f.apply(null, [1, 1]) // 2
(1) 找出数组最大元素
JavaScript 不提供找出数组最大元素的函数。结合使用apply方法和Math.max方法,就可以返回数组的最大元素。
var a = [10, 2, 4, 15, 9];
Math.max.apply(null, a) // 15
(2) 将数组的空元素变为undefined
通过apply方法,利用Array构造函数将数组的空元素变成undefined。
Array.apply(null, ['a', ,'b'])
// [ 'a', undefined, 'b' ]
空元素与undefined的差别在于,数组的forEach方法会跳过空元素,但是不会跳过undefined。因此,遍历内部元素的时候,会得到不同的结果。
var a = ['a', , 'b'];function print(i) {console.log(i);
}a.forEach(print)
// a
// bArray.apply(null, a).forEach(print)
// a
// undefined
// b
(3) 转换类似数组的对象
另外,利用数组对象的slice方法,可以将一个类似数组的对象(比如arguments对象)转为真正的数组。
Array.prototype.slice.apply({0: 1, length: 1}) // [1]
Array.prototype.slice.apply({0: 1}) // []
Array.prototype.slice.apply({0: 1, length: 2}) // [1, undefined]
Array.prototype.slice.apply({length: 1}) // [undefined]
(4) 绑定回调函数的对象
前面的按钮点击事件的例子,可以改写如下。
var obj = new Object();var func = function () {console.log(this === obj);
}var handler = function (){func.apply(obj);// 或者 f.call(obj);
};// jQuery 的写法
$('#button').on('click', handler);
3 Function.prototype.bind()
bind()方法用于将函数体内的this绑定到某个对象,然后返回一个新函数。
var d = new Date();
d.getTime() // 1481869925657var print = d.getTime;
print() // Uncaught TypeError: this is not a Date object.var print = d.getTime.bind(d);
print() // 1481869925657
bind方法的参数就是所要绑定this的对象,下面是一个更清晰的例子。
var counter = {count: 0,inc: function () {this.count++;}
};var func = counter.inc.bind(counter);
func();
counter.count // 1
this绑定到其他对象也是可以的。
var counter = {count: 0,inc: function () {this.count++;}
};var obj = {count: 100
};
var func = counter.inc.bind(obj);
func();
obj.count // 101
bind()还可以接受更多的参数,将这些参数绑定原函数的参数。
var add = function (x, y) {return x * this.m + y * this.n;
}var obj = {m: 2,n: 2
};var newAdd = add.bind(obj, 5); // 将x绑定为5
newAdd(5) // 20,将y绑定为5,x和y都有了,就可以运行了
如果bind()方法的第一个参数是null或undefined,等于将this绑定到全局对象,函数运行时this指向顶层对象(浏览器为window)。
function add(x, y) {return x + y;
}var plus5 = add.bind(null, 5);
plus5(10) // 15
bind()方法有一些使用注意点。
(1) 每一次返回一个新函数
bind()方法每运行一次,就返回一个新函数,这会产生一些问题。比如,监听事件的时候。
var listener = o.m.bind(o);
element.addEventListener('click', listener);
// ...
element.removeEventListener('click', listener);
(2) 结合回调函数使用
回调函数是 JavaScript 最常用的模式之一,但是一个常见的错误是,将包含this的方法直接当作回调函数。解决方法就是使用bind()方法,将counter.inc()绑定counter。
var counter = {count: 0,inc: function () {'use strict';this.count++;}
};function callIt(callback) {callback();
}callIt(counter.inc.bind(counter));
counter.count // 1
(3) 结合call()方法使用
利用bind()方法,可以改写一些 JavaScript 原生方法的使用形式,以数组的slice()方法为例。
[1, 2, 3].slice(0, 1) // [1]
// 等同于
Array.prototype.slice.call([1, 2, 3], 0, 1) // [1]
call()方法实质上是调用Function.prototype.call()方法,因此上面的表达式可以用bind()方法改写。
var slice = Function.prototype.call.bind(Array.prototype.slice);
slice([1, 2, 3], 0, 1) // [1]
这篇关于【JavaScript】this关键字:绑定this的方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!