js 中 this 的指向归类如下(总共有五种情况,全都是在严格模式下 , 不管哪种情况, this 返回的都是一个对象):
- 在函数体中,非显式或隐式地递减调用函数时,在严格模式下,函数内的 this 会绑定到 underfined 上, 在非严格模式下则会被绑定到全局对象 window / global 上。
- 一般使用 new 方法调用构造函数时,构造函数内的 this 会被绑定到新创建的对象上
- 一般通过 call / apply / bind 方法显式调用函数时,函数体内的 this 会被你绑定到指定参数的对象上
- 一般通过上下文对象调用函数时,函数体内的 this 会被绑定到该对象上
- 在箭头函数中, this 的指向是由外层(函数或全局)作用域来决定的, 箭头函数的 this 一旦确定就不可更改了
//例子1
function fn1() {
console.log(this); //window
}
fn1();
function fn2() {
'use strict'
console.log(this); // undefined
}
fn2();
//例子2
var foo = {
bar: 10,
fun() {
console.log(this);
console.log(this.bar)
}
}
var fn2 = foo.fun;
fn2(); // window undefineds
foo.fun() // {bar:10, fun:f} 10
//例子3 : 上下文对象
var studen = {
name: 'zhangsna',
fn() {
return this
}
}
console.log(studen.fn() === studen); // true
// 例子 4
var studen = {
name: 'zhangsna',
son: {
name: 'zhangxiaosan',
fn() {
return this.name;
}
}
}
console.log(studen.son.fn()) // zhangxiaosan
// 例子 5
var o1 = {
text: 'o1',
fn() {
return this.text;
}
}
var o2 = {
text: 'o2',
fn() {
return o1.fn();
}
}
var o3 = {
text: 'o3',
fn() {
var fn2 = o1.fn;
return fn2(); // 这里对 fn2 的调用是全局调用, 也就是普通函数的调用
}
}
console.log(o1.fn()); // o1
console.log(o2.fn()); // o1
console.log(o3.fn()); // undefined
//例子 6
var obj = {}
function fn() {
return this;
}
console.log(fn() === window) // true 这里是普通函数的调用
console.log(fn.call(obj) === obj) // true ,这里使用 call 改变了 this 的指向
//但是 call 绑定的对象是 null 、 undefined 或则为空 ,则结果仍是 window
console.log(fn.call()); // window
console.log(fn.call(null)); //window
console.log(fn.call(undefined)); //window
//如果call 传参不是以上类型,则转化成对应的包装对象
console.log(fn.call(5)) // Number{5}
// 例子 7
var counter = {
count: 0,
add() {
this.count++;
}
}
var fn = counter.add.bind(counter);
fn(); // 普通函数的调用,但是绑定了 this 指向
console.log(counter.count); // 1
var fn2 = counter.add;
fn2(); // 这里是普通函数的调用,没绑定 this
console.log(counter.count); // 1
//例子 8 bind() 返回的是一个函数
var counter = {
count: 0,
add() {
this.count++;
}
}
var obj = {
count: 100
}
var fn = counter.add.bind(obj);
fn();
console.log(counter.count); // 0
console.log(obj.count) // 101
//例子 9
var counter = {
count: 0,
add() {
'use strict'
this.count++;
}
}
function callback(fn) {
fn();
}
callback(counter.add.bind(counter));
console.log(counter.count); // 1
// 例子 10
var obj = {
name: 'zhangsan',
arr: [1, 2, 3],
print() {
this.arr.forEach(function (n) {
console.log(n)
console.log(this.name)
})
}
}
obj.print(); // 1 undefined 2 undefined 3 undefinde
// 例子 11
var obj = {
name: 'zhangsan',
arr: [1, 2, 3],
print() {
this.arr.forEach(function (n) {
console.log(n)
console.log(this.name)
}.bind(this))
}
}
obj.print(); // 1 zhangsan 2 zhangsan 3 zhangsan
// //例子 12
var obj = {
name: 'zhangsan',
arr: [1, 2, 3],
print() {
this.arr.forEach((n) => {
console.log(n)
console.log(this.name)
})
}
}
obj.print(); // 1 zhangsan 2 zhangsan 3 zhangsan
//例子 13
var x = 20;
const obj = {
x: 10,
test: function () {
console.log(this);
console.log(this.x);
}
}
obj.test(); // obj{} 10
// //例子 13
var x = 20;
const obj = {
x: 10,
test: () => {
console.log(this);
console.log(this.x);
}
}
obj.test(); // window 20
// 例子 14
var name = 'javascript';
const obj = {
name: 'php',
test: function () {
console.log(this) // obj{}
console.log(this.name) // php
const i = function () {
console.log(this)
console.log(this.name);
}
i(); // window javascript
}
}
obj.test(); // 这里的 i() 相当于是 全局普通函数的调用
//例子 15
var name = 'javascript';
const obj = {
name: 'php',
test: () => {
console.log(this) // window
console.log(this.name) // javascript
const i = function () {
console.log(this)
console.log(this.name);
}
i(); // window javascript
}
}
obj.test(); // 这里的 i() 相当于是 全局普通函数的调用
//例子 16
const a = 13
const obj = {
a: 13,
b: () => {
console.log(this.a)
},
c: function () {
console.log(this.a)
},
d: function () {
return () => {
console.log(this)
}
},
e: function () {
return this.b
}
}
obj.b(); // undefined
obj.c(); // 13
obj.d()(); // obj
obj.e()(); // underfined
提供一些更多的联系题链接:https://juejin.cn/post/6844904083707396109