「这是我参与2022首次更文挑战的第30天,活动详情查看:2022首次更文挑战」。
在上篇文章中我们介绍了this指向的前两个规则,默认绑定和隐式绑定javascript中的this指向总结(二)。本篇文章将介绍this指向的另外两个规则,显示绑定和new绑定。
规则三: 显示绑定
隐式绑定有一个前提条件:
- 必须在调用的对象内部有一个对函数的引用(比如一个属性)
- 如果没有这样的引用,在进行调用时,会找不到该函数的错误
- 通过这个引用,间接地将this绑定到了这个对象上 那么我们不希望在对象内部包含这个函数的引用,同时又希望在这个对象上进行强制调用,该怎么做呢?
function foo() {
console.log('函数被调用了');
}
foo()
当我们调用foo函数时,除了foo()直接调用外,还可以通过call和apply调用。
foo.call()
foo.apply()
call和apply和直接调用一样可以调用函数,它们的不同之处在于this绑定的不同。foo直接调用指向的是全局对象(window)。但是我不想让this指向的是全局对象。那么我们可以这样处理。
function foo() {
console.log('函数被调用了',this);
}
// foo()
/* foo.call()
foo.apply()
*/
var obj = {
name: 'obj',
foo: foo
}
obj.foo()
此时this指向的是obj对象。
但是我依然希望调用foo的时候this指向的是obj,但是不希望在obj对象中额外添加foo属性,此时我们可以通过call和apply来手动指定foo在调用的时候this的指向。
var obj = {
name: 'obj',
}
foo.call(obj)
foo.apply(obj)
foo.apply('aaa')
call和apply的区别
call和apply都可以调用函数,那么它们有什么区别呢?
call和apply第一个参数相同,后面的参数,call为参数列表,apply为数组。
function sum(num1, num2, num3) {
console.log(num1 + num2 + num3, this);
}
sum.call('call', 10, 20, 30)
sum.apply('apply', [10, 20, 30])
call和apply在执行函数时,是可以明确地绑定this,这个绑定规则称之为显示绑定。
显示绑定除了call和apply,还有bind。
bind绑定 如果我们想要修改this的绑定,可以使用call和apply。如果想要多次调用,就需要在每次调用的时候传入this的绑定,如以下代码。
function foo() {
console.log(this);
}
foo.call('aaa')
foo.call('aaa')
foo.call('aaa')
foo.call('aaa')
此时,我们可以使用bind更好的解决以上问题。通过bind传入this的绑定调用函数返回的是新函数,此时我们多次调用新函数不需要多次传入this的绑定。
var newFoo = foo.bind('aaa')
newFoo()
newFoo()
newFoo()
newFoo()
newFoo()
有一个疑问,我们通过newFoo()调用,这不是默认绑定吗,this不应该指向的是window吗?
这里有一个规则: 默认绑定和显示绑定bind冲突时,优先级较高的是显示绑定。
规则四: new绑定
javascript中的函数可以当做一个类的构造函数来使用,也就是使用new关键字。我们通过new关键字调用一个函数(构造器)时,这个时候this是在调用这个构造器时创建出来的对象,this=创建出来的对象,这个绑定过程就是new绑定。
function Person(name, age) {
this.name = name
this.age = age
}
var p1 = new Person('haha', 18)
console.log(p1.name, p1.age);
var p2 = new Person('xixi', 20)
console.log(p2.name, p2.age);