什么是this
this是函数内部的特殊对象,引用的是当前函数执行的环境对象。在执行期间无法被赋值。在全局执行环境中,this 都指向全局对象;在函数内部,this的指向取决于调用方式。
this的绑定规则
- 默认绑定
- 没有明确的调用对象时,
this
指向全局的window
对象。
function foo(){
console.log(this)
}
console.log(this); //window
foo(); // window
- 严格模式下,在函数内部时,如果 this 没有被执行环境定义,那它为undefined。
"use strict"
function foo(){
console.log(this)
}
console.log(this); //window
foo(); // undefined
- 不要被作用域迷惑,需判断是否有调用对象。也就是说,当作为独立函数调用时,无论处在什么位置,均指向
window
。
function foo(){
function bar(){
console.log(this)
}
bar();
}
foo(); // window
var obj = {
foo: function(){
function bar(){
console.log(this)
}
bar();
}
}
obj.foo(); //window
- 隐式绑定
某一对象的属性值为某个函数时,该函数的this就被隐性地绑定在该对象上。
- this的绑定是动态的,当函数执行时才绑定,而不是书写时绑定。 当该对象调用该函数时,
this
指向调用对象。若直接调用函数,依照上条规则,此时该函数作为独立的函数,this
指向window
对象。
function bar(){
console.log(this)
}
var obj = {
foo: bar,
}
obj.foo(); // obj
bar(); // window
- 若函数调用位置在一串对象属性链中,this绑定的是最内层的对象。
function bar(){
console.log(this)
}
var obj = {
a: 1,
foo1: {
a: 1,
foo2: {
a: 3,
foo3: bar
}
},
}
obj.foo1.foo2.foo3(); // {a: 3,foo3: bar};
关于this
丢失的问题:
function bar(){
var a = 'c';
console.log(this.a)
}
function baz(fn){
fn();
}
var obj = {
a: 'a',
foo: bar,
}
var a = 'b'
baz(obj.foo) // 'b'
var f = obj.foo;
f(); // 'b'
上述例子中,baz
的参数fn
与变量f
只是复制了存储在obj.foo
中的引用地址,指向bar
函数,与obj.foo
并无其他关系,因此baz
与f
执行时,bar
作为独立函数而不是obj.foo
的调用函数,this
绑定到了全局window
。
- 显式绑定
call与apply:都是用来设置函数体内this
对象的值,扩充函数运行的作用域,不需要任何耦合关系。
- 接受的第一个参数是运行函数的目标作用域,使对象能在目标作用域中调用执行。如果该参数不是对象,则内部
ToObject
操作将其转换为对象。 - 二者的区别在于接受的参数的方式不同,
call
需要逐个列举,apply
接收参数数组。 - 使用时立即调用函数。
bind:作用与前者类似, 区别在于bind
会创建并返回一个具有相同函数体和作用域的函数,称之为绑定函数。
- 不会立即执行,需要调用执行。
this
将永久地被绑定到了bind
的第一个参数,无论这个函数是如何被调用的,连续多次的bind
是无效的。
function bar(){
console.log(this.a)
}
function baz(fn){
fn();
}
var obj = {
a: 'a',
foo: bar,
}
var obj2 = {
a: 'c',
foo: bar,
}
var a = 'b'
var f = obj.foo;
f(); // 'b'
f.call(obj); //a
f.apply(obj); //a
var z = f.bind(obj);
z(); //a
f.bind(obj).bind(obj2)() // a
- new 绑定
new
运算符用来创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。使用new
创建实例的过程:
- 创建一个空的对象
{}
- 将构造函数的作用域赋给新对象,让this指向这个新对象
- 将新创建的对象作为
this
的上下执行构造函数中的代码,为新对象添加属性 - 返回新对象。
function Foo(){
this.name = 'Jane';
}
var foo = new Foo();
console.log(foo.name); // 'Jane'
参考文章
this - JavaScript | MDN
JavaScript函数中的this四种绑定形式
理解JS中的call、apply、bind方法