javascript this指向
阿新 • • 發佈:2020-12-05
在一些筆試題和專案中經常會出現一些this指向的問題。特此記錄一下
this的預設指向
1.全域性環境下this指向windowconsole.log(this) //window2.函式獨立呼叫,函式內部的this也指向window 3.被巢狀的函式獨立呼叫時,this預設指向了window
function fn1(){ console.log(this); //window } fn1() //fn1() === window.fn1(),所以指向了window var a = 1;4.IIFE自執行函式(自執行函式預設指向window,跟函式內部呼叫一致)var obj = { a:2, foo:function(){ // 函式當作物件的方法來呼叫時候,this指向obj var a = 3; var that = this; console.log(that.a) //2 function test(){ console.log(this.a); //1 } test() } } obj.foo()//獨立函式呼叫指向window
var a = 10; var obj = { a:2, foo:function(){ console.log(this); //函式當作物件的方法來呼叫時候,this指向obj (function test(){ console.log(this.a); })()5.閉包:this預設指向了window//自執行函式預設指向window,跟函式內部呼叫一致 } } obj.foo() // 10 var a = 10; var obj = { a:2, foo:function(){ console.log(this); //函式當作物件的方法來呼叫時候,this指向obj (function test(that){ console.log(that.a); })(this) //自執行函式預設指向window,跟函式內部呼叫一致 } } obj.foo() // 10
var a = 0; var obj = { a:2, foo:function(){ return function test(){ return this.a //閉包 :this預設指向了window } } } var bb = obj.foo() console.log(bb()) //0
6.隱式繫結
//當函式當作方法來呼叫,this指向了直接物件 function foo(){ console.log(this.a) } var obj = { a:1, foo:foo, obj2:{ a:2, foo:foo } } // foo()函式的直接物件是obj,this的指向指向了直接物件 obj.foo(); //1 obj.obj2.foo(); //2
7.隱式丟失
//隱式丟失就是指被隱式繫結的函式丟失了繫結物件,從而預設繫結到window //這種情況就是比較容易出錯卻又非常常見一、隱式丟失:函式別名
var a = 0; function foo(){ console.log(this.a) } var obj = { a:1, foo:foo } // 把obj.foo()賦值給別名bar,造成隱式丟失的情況,因為只是把obj.foo()賦值了給了bar變數,而bar與obj物件毫無關係 var bar = obj.foo; bar(); //0 相當於 var a = 0; var bar = function foo(){ console.log(this.a) } bar()
二、引數傳遞
// 2.引數傳遞 var a = 0; function foo(){ console.log(this.a) } function bar(fn){ fn() } var obj = { a:1, foo:foo } // 把obj.foo當作引數傳遞到bar函式中,有隱式的函式複製fn = obj.foo, 只是把foo函式賦值給了fn,而fn與obj物件毫無關係,所以當前foo函式內部的this指向了window bar(obj.foo) //0 等價於 var a = 0; function bar(fn){ fn() } bar(function foo(){ console.log(this.a); })
三、內建函式
// 3.內建函式 setTimeout()和setInterval()第一個引數的回撥函式中的this預設指向了window,跟第二種情況是類似 var a = 0; function foo(){ console.log(this.a) } var obj = { a:1, foo:foo } setTimeout(obj.foo,1000) //0 window
四、間接呼叫
// 4。間接呼叫 function foo(){ console.log(this.a) } var a = 0; var obj = { a:1, foo:foo } var p = {a:4} // obj.foo(); //1 // // 立即呼叫 // // 將obj.foo函式物件賦值給p.foo函式,然後立即執行。相當與僅僅是foo()函式的立即呼叫,內部的this預設指向了window // (p.foo = obj.foo)() //0 p.foo = obj.foo // 將obj.foo賦值給p.foo函式,之後p.foo()函式再執行,其實是屬於p物件的函式的指向,this指向當前的p物件 p.foo() //4
五、其他情況
//5.其他情況(指向了window的特殊情況) function foo(){ console.log(this.a) } var a = 0; var obj = { a:1, foo:foo } // 都是立即執行函式,指向window (obj.foo = obj.foo)() //0 (false || obj.foo)() //0 (1,obj.foo)() //0
8.顯示繫結
一、call() apply() bind()// call() apply() bind() 把物件繫結到this上,叫做顯示繫結 var a = 0; function foo(){ console.log(this.a); } var obj = { a:2 } foo() //0 window.foo() foo.call(obj) //2 foo.apply(obj) //2 var fn = foo.bind(obj) //2 fn()二、硬繫結是顯示繫結的一個變種,使得this不能再被改變
var a = 0; function foo(){ console.log(this.a); } var obj = { a:2 } var bar = function(){ foo.call(obj) } setTimeout(bar,2000) //2 bar.call(window) //2
三、陣列的forEach(fn,物件)//map()filter()some()every()第二個引數改變this指向
// 陣列的forEach(fn,物件) //map() filter() some() every()第二個引數改變this指向 var id = 'window'; var obj = { id:'fn' } var arr = [1,2,3] arr.forEach(function(el,index){ console.log(el,index,this); },obj)9.new繫結
function Fn() { //如果是new關鍵來執行函式,相當於建構函式來例項化物件,那麼內部的this指向了當前例項化的物件 console.log(this); //Fn {} } var fn = new Fn() console.log(fn); //Fn {} function Fn2(){ // this還是指向了當前的物件 console.log(this); // 使用return關鍵來返回物件的時候,例項化出來的物件是當前的返回物件 return { name:'zhen' } } var fn2 =new Fn2() //Fn2{} console.log(fn2) // {name: "zhen"} var Person ={ fav:function(){ return this } } var p = new Person.fav(); console.log(p); //fav {} console.log(p===Person.fav); //false // 例項化出來的物件內部的屬性constructor屬性指向了當前的建構函式 console.log(p.__proto__.constructor === Person.fav);
10.嚴格模式下this指向
//1.獨立呼叫的函式內部的this指向了undefined function fn(){ 'use strict' console.log(this); } fn() //undefined //2.嚴格模式下,函式apply()和call()內部this始終是他們的第一個引數 var color = 'red'; function showColor(){ 'use strict' console.log(this.color); } showColor.call(undefined)