不同环境下 function
的 this
的不同指向
- 事件调用环境 - 谁触发事件,函数里面的
this
就指向谁
// css
#div1,
#div2 {
width: 100px;
height: 100px;
background: #abcdef;
}
// html
// js
const div1 = document.getElementById('div1')
const div2 = document.getElementById('div2')
function click() {
this.style.background = 'red'
}
div1.onclick = click;
div2.onclick = click;
- 全局环境
a. 浏览器环境 -window
b.node
环境 -module.exports
// a
console.log(this); // window
// b
console.log(this === module.exports); // true
- 函数内部
a.this
最终指向的是调用它的对象
// 非严格模式下指向 window
function test() {
console.log(this)
}
test(); // 实际上是 window.test()
// 严格模式下指向 undefined
"use strict";
function test() {
console.log(this)
}
test();
var obj = {
a: 10,
fn: function () {
console.log(this)
}
}
obj.fn(); // obj
b. 函数被多层对象所包含,如果函数被最外层对象调用,this
指向的也只是它上一级对象
var obj = {
a: 10,
fn: function () {
console.log(this)
},
fn2: {
fn3: function () {
console.log(this)
}
}
}
window.obj.fn(); // obj
window.obj.fn2.fn3(); // fn2
var fn2 = obj.fn2;
fn2.fn3(); // fn2
var fn3 = obj.fn2.fn3;
fn3(); // window
c. 构造函数中的 this
指向的是实例对象
function fn() {
this.num = 1;
}
fn.num = 2;
fn.prototype.num = 3;
fn.prototype.getNum = function () {
console.log(this.num);
}
var prototype = fn.prototype;
var getNum = prototype.getNum;
new fn().getNum(); // 1
prototype.getNum(); // 3
getNum(); // undefined
注:new
一个构造函数的时候发生了什么?
1. 调用函数
2. 自动创建一个对象
3. 将创建出来的对象和 this
进行绑定
4. 如果构造函数返回的结果是一个对象,就返回这个对象;如果构造函数返回的不是一个对象,就返回创建的新对象。
d. 如果构造函数中有 return
,且 return
值是一个对象,this
指向返回的对象,如果不是对象或者为 null
,则保持原来规则(没有 return
时,隐式返回 this
)
function fn1() {
this.number = 1;
}
var obj1 = new fn1();
console.log(obj1.number); // 1
function fn2() {
this.number = 2;
return null
}
var obj2 = new fn2();
console.log(obj2.number); // 2
function fn3() {
this.number = 3;
return {
number: 4
}
}
var obj3 = new fn3();
console.log(obj3.number); // 4
function fn4() {
this.number = 4;
return []
}
var obj4 = new fn4();
console.log(obj4.number); // undefined
- 箭头函数 - 箭头函数本身是没有
this
和arguments
的,在箭头函数中引用this
,实际上调用的是定义时的上一层作用域的this
。(注意:对象是不能形成独立作用域的)
var obj = {
fn1: function () {
console.log(this, 'fn1');
},
fn2: () => {
console.log(this, 'fn2');
}
}
obj.fn1(); // obj
obj.fn2(); // window
修改 this 指向的方法
call
和 apply
的用法及异同详见:深入理解 call() 和 apply()
bind
: 只是修改 this
指向,但不会执行,实际上返回了一个 function