This 特点
简单来说,非严格模式下,全局 this 指向 window,其他的指向函数调用的执行主体,也就是谁调用,this 指向谁,注意,this 不是函数执行上下文。
此文不考虑 call bind apply 手动更改 this 的情况。
全局、非函数块级上下文中的 this
谈到this,基本就绕不开函数,脱离函数的this,全局上下文中都指向 windiw,严格模式下,this 为 undefined,而块级上下文没有自己的this。
console.log(this);
// -> 全局上下文中的this -> window
// -> 块级上下文中没有自己的this,所有 this 都是集成上级上下文中的 this(同箭头函数)
事件绑定中的 this
给当前元素的某个事件行为绑定方法「此时是创建方法,方法没执行」,当事件行为触发,浏览器会把绑定的函数执行,此时函数中的 this -> 当前元素对象本身。
- Dom 0:xxx.onxxx = function() {}
- Dom 2:xxx.addEventListener('xxx', function() {}), 不兼容 IE678
// ie 678 中的事件绑定 比较特殊 基于 attachEvent 声明的事件 this -> window
xxx.attachEvent('onxxx', function() {});
函数执行
正常函数执行
- 正常的普通函数执行,看函数执行前是否有"点",有的话,"点"前面是谁 this 就是谁,没有的话 this -> window(严格模式下是 undefined)
function fn() {
// 函数未被调用前 this 没解析 整个函数执行内容只是堆内存中的一堆字符串
console.log(this);
}
let obj = {
name: 'ys',
fn
}
fn() // window
obj.fn(); // obj
2. 括号表达式执行函数:小括号中包含"多项",这样也只取最后一项去当做函数执行,但是 this 受到影响,一般指向 window / undefined。
(obj.fn)(); // obj 只包含一项的时候没有变化
(10, obj.fn)(); // this -> window
匿名函数执行
函数表达式
什么是函数表达式?所有不以 function 开头声明的函数都是函数表达式。
- this 指向 window,非严格模式下指向 undefined
- 函数表达式的函数名外部不能访问(内部能访问),内部不能修改
var fn = function fn2() {
fn2 = 2;
console.log(fn2); // function
}
自执行函数
- 本身也属于函数表达式,所以和函数表达式行为一致。
- 执行完毕后,存储函数执行体的堆内存会被释放掉,没有变量去接收(引用)函数,用完就丢,但是执行栈不一定释放,取决于自执行函数里有没有继续被引用,比如 return 一个函数被外部引用,则形成闭包。。
(function fm() {
fm = 2;
console.log(this); // window
console.log(fn); // function
})();
回调函数
把一个函数 cb 作为实参,传递给另外一个函数 fn 去执行。 行为同普通函数调用。看函数执行前是否有"点",有的话,"点"前面是谁 this 就是谁,没有的话 this -> window(严格模式下是 undefined)
function cb() {
console.log(this); // window
}
function fn(cb) {
cb();
}
// forEach 循环中的回调函数
var arr = [1, 2, 3]
arr.forEach(function(item, index) {
console.log(this); // window, 也是回调函数的场景
});
arr.forEach(function(item, index) {
console.log(this); // { a: 1 } // forEach 内部封装
}, { a: 1 });
一道有趣的题
var x = 3;
var obj = {
x: 5
}
obj.fn = (function() {
this.x *= ++x;
return function(y) {
this.x *= (++x) + y;
console.log(x);
}
})()
var fn = obj.fn;
obj.fn(6);
fn(4);
console.log(obj.x, x);
参考以下图示:
补手绘更详细图解:
// 13
// 234
// 95 234