javaScript中this的指向?
javaScript中this对象是在运行时基于函数的执行环境绑定的,在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。
但在实际中,代码环境复杂,this的指向并非那么直接判断出来。下面来做一下总结。
1,全局执行环境下的普通函数
function f1 () { console.log(this) } function f2 () { 'use strict' console.log(this) } f1() // window f2() // undefined
分为严格模式和非严格模式。非严格模式下等于window,严格模式下为undefined。
2,事件对象中的this
this指的是事件对象本身,是指event.target
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="div1">我是一个div</div> <script> window.id = 'window' document.getElementById('div1').onclick = function (){ alert(this.id) // 输出div1 } </script> </body> </html>
3,对象中的方法引用
const foo = { bar: 10, fn: function() { console.log(this) console.log(this.bar) } } foo.fn() // this指的是foo var fn1 = foo.fn fn1() // this指的是window
4,构造函数中的this
// this指instance function Foo() { this.bar = "ceshi" } const instance = new Foo() console.log(instance.bar) // this指的是 {} function Foo(){ this.user = "ceshi"
const o = {} return o } const instance = new Foo() console.log(instance.user)
这里的this之所以不同是由构造返回值是否是对象导致的
5,丢失的this
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="div1">我是一个div</div> <script> let getId = document.getElementById console.log(getId('div1')) // 报错,报错这是因为document.getElementById方法内的this指向window导致的 // 修复 document.getElementById = (function(func){ return function(){ return func.apply(document,arguments) } })(document.getElementById) let getId = document.getElementById console.log(getId('div1')) </script> </body> </html>
6,借助bind、Object.prototype.call和Object.prototype.apply改变this的指向
Object.prototype.call和Object.prototype.apply的是后者参数为数组,前者为多个参数。
用代码来总结: const target = {} fn.call(target, 'arg1', 'arg2') 相当于: const target = {} fn.apply(target, ['arg1', 'arg2']) 相当于: const target = {} fn.bind(target, 'arg1', 'arg2')()
借助call改变
const foo = { name: 'ceshi', logName: function() { console.log(this.name) } } const bar = { name: 'mike' } console.log(foo.logName.call(bar)) // mike
7,其他一些复杂的场景
const foo = { fn: function () { setTimeout(function () { console.log(this) }) } } foo.fn() // this===window
let,const不会挂在window上面,而var可以
const a = 999 let aa = 1000 var b =1001 function too(){ console.log(this.a) console.log(this.aa) console.log(this.b) } too()
对象嵌套中的this
const person = { name: 'ceshi', brother: { name: 'zhen', fn: function() { return this.name } } } console.log(person.brother.fn()) // zhen
更复杂的情景
const o1 = { text: 'o1', fn: function () { return this.text } } const o2 = { text: 'o2', fn: function () { return o1.fn() } } const o3 = { text: 'o3', fn: function () { var fn = o1.fn return fn() } } console.log(o1.fn()) // o1 console.log(o2.fn()) // o1 console.log(o3.fn()) // undefined
箭头函数的this提前绑定好
const foo = { fn: function () { setTimeout(() => { console.log(this) }) } } console.log(foo.fn()) // {fn: ƒ}
8,通过 call、apply、bind 绑定的情况称为显式绑定;根据调用关系确定的 this指向称为隐式绑定。那么哪一个优先级更高呢?
function foo (a) { console.log(this.a) } const obj1 = { a: 1, foo: foo } const obj2 = { a: 2, foo: foo } obj1.foo.call(obj2) // 2 obj2.foo.call(obj1) // 1
显式绑定的优先级高于隐式绑定。
我站在山顶看风景!下面是我的家乡!