抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >
this到底指向什么?

函数在调用时,JavaScript会默认给this绑定一个值

this的绑定和定义的位置(编写的位置)没有关系

this的绑定和调用方式以及调用的位置有关系

this是在运行时被绑定的


this 绑定规则

this的绑定规则

  • 绑定一:默认绑定

  • 绑定二:隐式绑定

  • 绑定三:显示绑定

  • 绑定四:new绑定

默认绑定

独立的函数调用可以理解成函数没有被绑定到某个对象上进行调用

严格模式,独立调用的函数中的this指向的是undefined

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 1. 普通函数被独立调用
function foo () {
console.log('foo ', this);
};

foo(); // 指向window

// 2. 函数定义在对象中,但是独立调用
const obj = {
name: 'why',
bar: function () {
console.log('bar ', this);
},
};

// obj.bar(); // 指向obj对象

const baz = obj.bar;
baz() // 指向window

// 3. 严格模式,独立调用的函数中的this指向的是undefined

案例

案例一

1
2
3
4
5
function () {
console.log(this);
}

foo()

案例二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function test1 () {
console.log(this);
test2();
}

function test2 () {
console.log(this);
test3();
}

function test3 () {
console.log(this);
}

test1();

案例三

1
2
3
4
5
6
7
8
9
10
11
12
13
// 高阶函数
function foo (func) {
func()
}

const obj = {
name: 'why',
bar: function () {
console.log(this);
}
}

foo(obj.bar); // 属于独立调用

隐式绑定

通过某个对象进行调用;也就是它的调用位置中,是通过某个对象发起的函数调用

隐式绑定的前提条件

  • 必须在调用的对象内部有一个对函数的引用(比如一个属性);
  • 如果没有这样的引用,在进行调用时,会报找不到该函数的错误;
  • 正是通过这样的引用,间接的将this绑定到这个对象上;
1
2
3
4
5
6
7
8
9
10
11
// 隐式绑定
function foo () {
console.log(this);
}

const obj = {
bar: foo,
}

obj.bar(); // 指向obj对象

案例

案例一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function foo () {
console.log(this);
}

const obj = {
name: 'obj',
foo: foo,
}

const obj2 = {
name: 'obj2',
obj1: obj2,
}

obj2.obj1.foo(); // 指向obj1对象

案例2

1
2
3
4
5
6
7
8
9
10
11
function foo () {
console.log(this);
}

const obj1 = {
name: 'obj1',
foo: foo,
}

const bar = obj1.foo;
bar(); // 指向obj1对象

显式绑定

不希望在对象内部包含这个函数的引用,同时又希望在这个对象上进行强制调用;可以使用显式绑定

call和apply方法

  • 第一个参数是相同的,要求传入一个对象
    • 这个对象的作用就是给this准备的
    • 在调用这个函数时,会将this绑定到这个传入的对象上
  • 后面的参数;apply为数组,call为参数列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function foo (name, age, height) {
console.log('foo 函数被调用 ', this);
console.log('打印参数 ', name, age, height);
}

// ()调用
// foo('why', 18, 180);

// apply
// 第一个参数:绑定this
// 第二个参数:传入额外的实参,以数组的形式
// foo.apply('apply', ['kobe', 30, 198])

// call
// 第一个参数:绑定this
// 第二个参数:后续的参数以多参数的形式传递,会作为实参
foo.call('call', 'james', 35, 205);

bind 的显示绑定

  • 如果我们希望一个函数总是显式的绑定到一个对象上,可以使用 bind 方法;bind()方法创建一个新的绑定函数(bound function, BF)
  • 绑定函数是一个exotic function object(怪异函数对象,ECMAScript 2015 中的术语)
  • 在bind() 被调用时,这个新函数的this被指定为bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function foo (name, age, height) {
console.log('foo ', this);
}

const obj = { 'name': 'why' };

// 需求:调用foo时,总是绑定到obj对象身上(不希望obj对象上有函数)
// 1. bind函数的基本使用
const bar = foo.bind(obj);
bar(); // this --> obj

// 2. bind函数的其他参数
const test = foo.bind(obj, 'kobe', 30, 198)
test()

new绑定

JavaScript中的函数可以当做一个类的构造函数来使用,也就是使用new关键字

使用new关键字调用函数执行的操作

  1. 创建新的空对象;
  2. 新对象会被执行prototype连接;
  3. 新对象会绑定到函数调用的this上(this绑定在这个步骤完成);
  4. 没有显示返回非空对象时,默认返回这个对象;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function foo () {
this.name = 'why';
console.log(this);
}

new foo(); // 指向foo对象

// 创建Person
function Person (name) {
console.log(this); // Person {}
this.name = name; // Person { name: 'why' }
}

const p = new Person('why');
console.log(p);

内置函数的调用绑定

评论