全局代码中的this
-
全局中的代码不管是否处于严格模式下,它的this都执行Window
console.log(this) // Window 复制代码
箭头函数的this
- 箭头函数的this由上下文的词法作用域决定,即在哪定义的就指向哪里的this
() => {
console.log(this) // window 或 global,在全局定义指向全局
}
obj = {
fn: () => {
console.log(this) // obj 在obj对象中定义,指向obj
}
}
复制代码
普通函数中的this
-
直接调用函数(在全局或者其他函数内)
-
在非严格模式下,this默认指向全局变量(window或global)
```js // 在浏览器中,全局对象是window, 在NODE中是global function test() { console.log(this) // Window 或者 global (function(){ console.log(this) // Window 或者 global }) } test() ``` 复制代码
- 在严格模式下,this将保持进入执行环境的值,所以,如果没有指定环境,则默认undefined
function test() { console.log(this) // undefined (function(){ console.log(this) // undefined }) } test() 复制代码
- 特殊点:当函数作为回调函数时,需要注意是否隐式绑定了所属对象,例如:当作为setTimeout的参数时,就默认将函数绑定了window对象
// setTimeout是window的方法,可以使用window.setTimeout调用 // 调用函数时,对象访问大致路线:window -> setTimeout -> 获取参数中test的引用参数 -> 执行 test 函数 function test() { console.log(this) } setTimeout(test, 100); // window 或 global 复制代码
-
-
作为对象方法调用则指向当前对象
- 注意:如下列代码中的将对象的方法赋值给其他变量在调用,this将按上面的普通方法直接调用函数规则处理
var a = 'global' function name() { console.log('name', this.a) // 通过普通调用方法直接调用,在严格模式下this为undefined,运行报错,在非严格模式下global } var obj = { fn: function () { console.log('inner', this.a) // obj 通过对象obj调用,this指向该对象与模式没有关系 name() }, a: 'obj' } obj.fn() var newFn = obj.fn() newFn() // 严格模式为undefined,非严格为window或者global,按普通方法直接调用的规则处理 function test(fn){ fn() } test(obj.fn) // 相当于将fn=obj.fn, 严格模式为undefined,非严格为window或者global newObj = {fn: 2} test(newObj.fn=obj.fn) // 相当于 fn = newObj.fn = obj.fn, 严格模式为undefined,非严格为window或者global 复制代码
-
执行new操作时,构造函数的this指向正在构造的新对象
function TEST(){ this.a = 'obj'; console.log(this) //new操作时 TEST { a: 'obj'} this指向正在构造的对象(返回的对象) } var o = new TEST(); console.log(o); // TEST { a: 'obj'} this指向刚刚构造的对象 复制代码
- 对es6的class Person {} 使用new操作时,this执行它调用的环境
class MyTest { constructor (callback) { this.callback = callback callback() // 指向window } func () { this.callback() // 指向MyTest } } // let的值不会绑定到window上,无法用window.name访问 let name = 'global' function Test () { console.log(this, this.name) } new Test() // window 使用let输出 '', 使用var输出global let c = new MyTest(Test) // window 使用let输出 '', 使用var输出global c.func() // MyTest{} undefined 复制代码
- 其他情况下Constructor的执行与普通函数没有区别,谁调用它则指向谁
// 当函数直接调用的时候,在非严格模式下,this指向window;严格模式为undefined // 当函数作为对象的属性调用的时候,this指向这个对象; // p1.constructor指向Person的构造函数(Person()函数本身), // 在p1.constructor()时,Person是作为p1的属性调用的,所以this指向p1; // 当调用p2 = p1.constructor;p2();时,其实就相当于直接调用Person();所以this指向window var name = 'global' function Person() { this.name = 'person'; console.log(this); } var p1 = new Person(); p1.constructor(); // Person {name: "person"} var p2 = p1.constructor; p2(); // window 复制代码
-
设置call/apply/bind后调用,则指向其第一个参数的this,如果为空则在严格模式下指向undefined,在非严格模式下指向window或global
// 语法 // 1、函数.apply(对象, [参数列表]) // 2、函数.call(对象, arg1,arg2,arg3…argn) // 3、函数.bind(对象) // 'use strict' var a = 'global' function name() { console.log('name', this.a) } function name2() { console.log('name2', this) } var obj = { a: 'obj' } name.call(obj) // obj this指向通过call绑定的obj对象 // name2.call() // 严格模式为undefined,非严格模式为widow或global 复制代码
-
作为一个dom事件处理函数,它的this指向添加处理事件的元素(一些浏览器在使用非addEventListener的函数动态添加监听函数时不遵守这个约定)
// html <div id="A"> <div id="B"></div> </div> // javascript var a = document.getElementById('A'); var b = document.getElementById('B'); function logs (e) { console.log(e.target, e.target===this); // 当e.target与e.currentTarget相等时为true console.log(e.currentTarget, e.currentTarget===this); // 总是true } a.addEventListener('click', logs, false); // 点击A时, // 输出 A节点信息,true \n A节点信息, true // 点击B时, // 输出 B节点信息,false \n A节点信息, true // currentTarget表示实际绑定处理事件的元素 // target表示触发事件的元素(如点击B) // 所以处理事件中的this指向实际添加处理事件的元素 复制代码
-
作为一个内联事件处理函数,
- 当代码被内联on-event 处理函数调用时,它的this指向监听器所在的DOM元素,与模式没有关系
<button onclick="alert(this.tagName.toLowerCase());">Show this</button> 复制代码
- 当代码包裹在内部函数中时,在非严格模式指向window或global对象(即非严格模式下调用的函数未设置this时指向的默认对象),在严格模式下为undefined
<button onclick="alert((function(){return this})());">Show inner this</button> 复制代码