this的指向
/**
* 直接调用,this指向window
* @returns Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}
* */
console.log(this);
/**
* 普通函数调用,this指向window
* @returns Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}
* */
function test() {
console.log(this);
}
test();
/**
* 构造函数创建的实例调用,this指向创建的实例对象
* @returns Person {name: "老王", age: 44, say: ƒ}
* */
function Person(name, age) {
this.name = name;
this.age = age;
this.say = function () {
console.log(this);
}
}
const p1 = new Person('老王', 44);
p1.say();
/**
* 对象调用其内部方法,this指向当前对象
* @returns {name: "老黄", fn: ƒ}
* */
const obj = {
name: '老黄',
fn: function() {
console.log(this);
}
};
obj.fn();
/**
* 外部调用对象内部方法,this指向window
* @returns Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}
* */
let myFn = obj.fn;
myFn();
/**
* 定时器(setInterval/setTimeout)是window的方法,相当于window.setTimeout,平时一般省略window
* 定时器的回调函数中的this指向window
* @returns Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}
* */
function Person() {
setTimeout(function() {
console.log(this);
}, 3000);
}
var p = new Person();
/**
* 修改定时器中的this,可以用bind / call / apply绑定自定义对象
* @returns Person {}
* */
function Person() {
setTimeout(function() {
console.log(this);
}.bind(this), 3000);
}
var p = new Person();
/**
* 修改定时器中的this,保存上一级this =》 const _this = this;
* 实际开发中,也有一些人这样写,我觉得也不错
* @returns Person {}
* */
function Person() {
const _this = this;
setTimeout(function() {
console.log(_this);
}.bind(this), 3000);
}
var p = new Person();
/**
* 绑定事件调用,this指向绑定事件的元素
* @returns <button id="BT">按钮</button>
* */
const BT = document.querySelector('#BT');
BT.onclick = function () {
console.log(this);
};
/**
* 箭头函数体内的this对象,就是 定义该函数时所在的作用域 指向的对象,而不是使用时 所在的作用域 指向的对象。
* 箭头函数sayHello,所在的作用域是Person{},由于Person{}外层没有包裹函数,所以Person{}指向的对象是window,所以箭头函数内部的this指向window
* @returns window
* */
var name = 'window';
var Person = {
name: 'A',
sayHello: () => {
console.log(this.name)
}
};
Person.sayHello();
this指向练习题
/**
* A:
* fn的this指向window
* let声明的变量不挂载在window对象上
* 输出结果为:window.len = undefined
*
* B:
* fn的this指向window
* say中的this指向Person,fn虽然在Person中的say中,但是fn()前面没有. -- XXX.fn(),所以算是window.fn()
* 输出结果为:window.len = undefined
*
* C:
* arguments保存所有传递给该函数的参数,本质是一个伪数组
* fn的this指向arguments
* arguments[0]() = argument.fn()
* 输出结果为: arguments.len = undefined
* */
let len = 10;
function fn() {
console.log(this.len)
}
fn(); // A
let Person = {
len: 5,
say: function() {
fn(); // B
arguments[0](); // C
}
};
Person.say(fn);
/**
* A:
* 这里 var 定义的变量是 全局变量
* 输出结果为: window.length = 10
*
* B:
* 输出结果为: window.length = 10
*
* C:
* arguments.fn() => this指向arguments,上面说了arguments是一个伪数组 this.length === arguments.length
* 输出结果为:1
* */
var length = 10;
function fn() {
console.info(this.length)
}
fn(); // A
let Person = {
len: 5,
say: function() {
fn(); // B
arguments[0](); // C
}
};
Person.say(fn);
/**
* A:
* A.apply(this,arguments) === A(arguments) A中的this指向B === B.name = arguments
* prototype中的方法可以被构造函数创建出来的对象共享
* 输出结果为: TOM
* */
var A = function( name ) {
this.name = name;
};
var B = function() {
A.apply(this,arguments);
};
B.prototype.getName = function() {
return this.name;
};
var b = new B('TOM');
console.log( b.getName() ); // A
/**
* A:
* 定义箭头函数fn时,所在的作用域Person{},person{}指向window,所以箭头函数中的this指向window
* 执行箭头函数fn时,所在的作用域Person{},person{}指向window
* 输出结果为:1
*
* B:
* 定义箭头函数fn时,所在的作用域Person{},person{}指向window,所以箭头函数中的this指向window
* 执行箭头函数fn时,所在的作用域Person{},person{}指向Person
* 输出结果为:1
* */
var a = 1;
var Person = {
a: 2,
fn: () => console.log(this.a)
};
var ofn = Person.fn;
ofn(); // A
Person.fn(); // B
/**
* A:
* 定义箭头函数时,所在的作用域sayHello{},sayHello{}指向Person,所以箭头函数中的this指向Person
* 执行箭头函数时,所在的作用域sayHello{},sayHello{}指向window
* 输出结果为:A
*
* B:
* 定义箭头函数时,所在的作用域sayHello{},sayHello{}指向Person,所以箭头函数中的this指向Person
* 执行箭头函数时,所在的作用域sayHello{},sayHello{}指向B
* 输出结果为:A
*
* C:
* 定义箭头函数时,所在的作用域sayHello{},sayHello{}指向Person,所以箭头函数中的this指向Person
* 执行箭头函数时,所在的作用域sayHello{},sayHello{}指向window
* 输出结果为:A
* */
var name = 'window';
var Person = {
name: 'A',
sayHello: function(){
var res = () => console.log(this.name);
return res
}
};
var sayHello = Person.sayHello();
sayHello(); // A
var B = { name: 'B'};
sayHello.call(B); // B
sayHello.call(); // C
参考文章
- https://zhuanlan.zhihu.com/p/136732548
- https://www.jb51.net/article/151599.htm
- https://www.cnblogs.com/peaky/p/js-this.html
- https://zhuanlan.zhihu.com/p/57204184