含义
this表示当前对象的引用
指向
- 在方法中,this表示方法所属的对象
- 单独使用,this表示全局对象
- 在函数中,this表示全局对象
- 在事件中,this表示接受事件的元素
- 在call(),apply()中,this表示传入的参数对象
绑定规则
默认绑定,隐式绑定,显示绑定,new绑定。优先级从低到高
默认绑定
非严格模式
function say () {
console.log(this.a);
}
var a = 1;
say();
输出:1
解析:因为函数say是直接调用(独立调用的),所以函数里面的this指向全局,全局中的a值为1,所以最后输出 为1
严格模式
function strictSay () {
'use strict'
console.log(this.b);
}
var b = 'b';
strictSay();
输出:Uncaught TypeError: Cannot read properties of undefined (reading 'b')
解析:严格模式下,全局对象无法使用默认的绑定,无法直接使用this,所以在输出的时候,直接报错了
隐式改变
绑定
function say() {
console.log(this.name);
}
const doy = {
name: 'dog',
say: say
}
dog.say();
输出:dog
解析:此时say为dog对象上的属性,所以 this指向的是dog对象,所以输出 dog
丢失
const cat = {
age: 1,
say: function() {
console.log(this.age)
}
};
cat.say();
const say = cat.say;
say();
输出:
- cat
- undefined
解析:第一次调用的时候this指向的cat,第二次调用的时候this指向全局
显示绑定
call/apply
call和apply都能改变函数中的指向,将函数的this指向传入的参数。
call只接受两个参数,第一个为this需要指向的对象,第二个为函数的参数(数组形式)
appiy可以接受多个参数,第一个参数this需要指向的对象,后续参数为 函数的参数
const obj = {
text: 'obj'
};
function getContent () {
console.log(this.text);
}
getContent.call(obj);
输出:obj
解析:如果直接执行getContent函数,this指向全局。但是在这儿使用了call改变了函数内部的this指向,指向参数obj,所以最后输出 obj
bind
将函数绑定到某个对象,且绑定后不可以改变
function bindFunc () {
console.log(this.content);
}
const bindObj = {
content: 'bindObj'
}
var content = 'window';
bindFunc.bind(bindObj).bind(window)();
bindFunc();
输出:
- bindObj
- window 解析:bind只第一次使用的时候才会生效,第二个 bind(window)是无用代码,所以第一个输出的是 bindObj
new 绑定
function Person (age) {
this.age = age;
}
var age = 10;
var person1 = new Person(12);
persion1.age;
输出:12
解析:this指向对象自身
面试题
题目1 对象属性
var obj = {
a: 10,
b: this.a + 10,
fn: function() {
console.log(this.a);
}
}
console.log(obj.b);
console.log(obj.fn());
输出:
- NaN 解析:此时this指向的window
- 10 解析:this指向的obj自身
题目2 声明时,决定作用域
var a = 1;
function fn() {
var a = 2;
console.log(a);
console.log(this.a);
}
function fn2() {
var a = 3;
fn();
}
var obj = {
a: 4,
fn: fn
}
fn2();
obj.fn();
输出:
- 2 解析:a为当前(fn)作用域的变量
- 1 解析:在fn2 中独立调用了 fn,fn中的this指向全局
- 2 解析:a为当前(fn)作用域的变量
- 4 解析:将fn的值赋值给obj的fn属性的值,所以执行 obj.fn 时,this指向obj
题目3 赋值改变this指向
function foo() {
console.log(this.a);
}
var a = 1;
var obj = {
a: 2,
foo: foo
};
var p = { a: 3 };
obj.foo();
(p.foo = obj.foo)();
输出:
- 2 解析:this指向obj
- 1 解析:这是一个赋值语句,最后的返回值是foo,然后再单独调用,this指向全局
题目4 this的指向
function foo (arg) {
this.x = arg;
return this;
}
var x = foo(1);
var y = foo(2);
console.log(x.x);
console.log(y.x);
输出:
- Window对象(x属性存在循环引用)
- 2
解析:两次调用都是独立调用,所以this都指向的window。
var x = foo(1);执行完成之后,x的值是 window;var y = foo(2);执行完后,y的值是window,x的值是 2;所以在后续输出的时候 2.x输出的是 undefined,window.x输出的值是 2.
题目5 不同语句的返回值
var a = 1;
var obj = {
a: 2,
foo: function() {
var a = 3;
console.log(this.a);
}
}
obj.foo();
(obj.foo)();
(obj.foo = obj.foo)();
(obj.foo, obj.foo)();
输出:
2解析:此时this指向obj2解析:和前一行调用一样1解析:赋值语句,返回值为函数值,所以和单独调用foo函数一样,所以此时this指向全局1解析:小括号运算,返回最后一个的值,所以1
面试6 严格模式下window 和 this
'use strict'
var a = 1;
function foo () {
console.log('this1', this);
console.log(window.a);
console.log(this.a);
}
console.log('this2', this);
console.log(window.a);
foo();
输出:
this2 Window对象1this1 undefined1VM567:5 Uncaught TypeError: Cannot read properties of undefined (reading 'a')解析:严格模式下,函数内部无法通过this访问到全局的window对象,单独调用时是 this为undefined
题目7 var 和 let
const a = 10;
let b = 20;
function foo () {
console.log(this.a);
console.log(this.b);
}
foo();
console.log(window.a);
输出:三个undefined
解析:用const 和 let定义的变量不会挂在全局,一定要注意声明使用的什么修饰。
题目8 箭头函数中的this
var name = 'window';
var obj = {
name: 'obj',
foo: function() {
console.log(this.name);
return () => {
console.log(this.name);
}
},
foo1: () => {
console.log(this.name);
return function () {
console.log(this.name);
}
}
}
var obj2 = { name: 'obj2' };
obj.foo.call(obj2);
obj.foo().call(obj2);
obj.foo1.call(obj2);
obj.foo1().call(obj2);
输出:
obj2解析:call将 obj.foo的 this 指向了obj2,所以输出obj2obj obj解析:obj.foo执行时 this指向的obj,所以输出obj;在执行call无法改变尖头函数的this的指向,所以this为上层函数this的指向,所以输出objwindow解析:箭头函数this指向为上一层的this指向(call无法改变尖头函数内部this的指向),所以指向的window,输出windowwindow obj2解析:尖头函数this指向window(上一级),call改变return出来函数的this指向,所以输出obj2
题目9 数组调用
var length = 1;
function callback() {
return this.length;
}
var obj = {
length: 2,
say: function() {
arguments[0]();
}
}
obj.say(callback, 1, 2);
输出:3
解析:this指向arguments,所以长度时3