摘要:回調函數中調用在回調函數中一般有兩種情況回調函數為匿名函數時,回調函數的會指向,需要對回調函數。回調函數為箭頭函數時,回調函數的會指向他的直接上層。
淺談-this
this簡單而又神秘,使用場景多變而又復雜,這造就了它成為了初級javascript開發人員不愿接觸的東西,高級javascript都想探究的東西。文本亦是對this的致敬。
this是什么?
this是當前執行環境的上下文,通常由函數的調用方式決定其值。
this的原理
首先,從函數的調用開始
函數的調用一般有三種情況(ES5中)
1.foo(p1,p2);
2.obj.foo(p1,p2);
3.foo().call(context,p1,p2);//或者apply
通常情況下,大部分童鞋常用的都是前兩種方式,只有在不得不綁定context的情況下才會使用第三種。其中,第三種方式,才是函數調用的正確方式。
foo().call(context,p1,p2);
之所以,我們在使用前兩種方式也能正常的運行,這其實就是一種語法糖而已,在js運行機制中,會把前兩種調方式,當做下面的方式進行處理
foo(p1, p2) 等價于 foo.call(undefined, p1, p2) obj.foo(p1, p2) 等價于 obj.foo.call(obj, p1, p2)
因此,如果我們以后再調用函數時,能準確的找到context,就可以唯一的確認this的值
this的使用場景
3.1 全局環境使用
無論是否在嚴格模式下,在全局執行環境中(在任何函數體外部)this 都指向全局對象。
// 在瀏覽器中, window 對象同時也是全局對象:
console.log(this === window); // true
var a=1;
console.log(this.a) //1
console.log(window.a) //1
3.2 普通函數中調用
在非嚴格模式下,且this的值沒有被調用函數設置,this 的值默認指向全局對象。
funnction func(){ console.log(this) } //瀏覽器環境中 func() // window //node環境中 func() // global
在嚴格模式下,this的值如果不設置,就是是undefined
funnction func(){ "use strict" console.log(this) } func() === undefined; // true
3.3 作為對象中的方法調用
var obj={
name:"我是對象obj", ofun:function(){ console.log(this.name) } } var name="我是全局name"; var func= obj.ofun; obj.ofun(); //我是對象obj func(); //我是全局name
這里有兩點需要注意:
1.函數作為對象的方法進行調用時,this指向當前的對象。 2.對象中的函數方法名存儲的僅是一個函數的地址(地址中會有該函數的屬性:[[value]、[[writable]]、[[enumerable]]、[[congifable]]) 當把一個對象的方法賦值給另一個變量(例如:func)時,引擎會將函數多帶帶保存在內存中,然后再將函數的地址賦值給foo屬性的value屬性。
3.4 構造函數中使用
this在構造函數中使用,值為實例化的對象
function Fun(name){ this.name=name; this.speak=function(){ console.log(this.name); } } var fun1=new Fun("jack"); fun1.speak(); var fun2=new Fun("rose"); fun2.speak();//rose
3.5 bind/call/apply
this再被bind/call/apply強制綁定上下文執行環境時,屬于硬綁定。
function foo(somerthing){ console.log(this.a); } var obj={ a:2 } var bar = function(){ foo.call(obj); }; bar(); //2 //硬綁定的bar不可能再修改它的this bar.call(window);//2 }
硬綁定的典型應用場景就是創建一個包裹函數,傳入所有的參數并返回接收到的所有值;
function foo(somerthing){ console.log(this.a,something); return this.a +something; } var obj={ a:2 } var bar = function(){ return foo.apply(obj,arguments); }; var b=bar(3);// 2 3 console.log(b);//5
由于硬綁定是一種非常常用的模式,所以在ES5中提供了內置的方法Function.prototype.bind,它的用法如下;
function foo(somerthing){ console.log(this.a,something); return this.a +something; } var obj={ a:2 } var bar=foo.bind(obj); var b=bar(3);// 2 3 console.log(b);//5
call,apply,bind方法的區別:
a:第一個參數都是要綁定的上下文執行環境,即this的值。
b:都可在函數調用時傳遞參數。call,bind方法需要直接傳入,而apply方法需要以數組的形式傳入。
c:call,apply方法是在調用之后立即執行函數,而bind方法沒有立即執行,需要將函數再執行一遍。有點閉包的味道。
d:改變this對象的指向問題不僅有call,apply,bind方法,也可以使用that/self等變量來固定this的指向。
3.6 回調函數中調用
在回調函數中一般有兩種情況: 1. 回調函數為匿名函數時,回調函數的this會指向window,需要對回調函數bind(this)。 2. 回調函數為箭頭函數時,回調函數的this會指向他的直接上層。
var obj = { name: "test for call-func", ofun: function(){ //undefined 丟失 setTimeout(function(){ console.log(this.name) }, 100); //work well 硬綁定 setTimeout(function(){ console.log(this.name) }.bind(this), 100);//test for call-func // arrow function test for call-func setTimeout( () => console.log(this.id), 100) } }; obj.ofun();
3.7 自執行函數
自執行或者立即執行函數中的this指向Window
首先自執行函數的幾種調用方式
//常見的有兩種: (function(){})() (function(){}())//w3c推薦方式 //只有表達式才能被執行符號()執行 +function test(){}();//+ - ! =等運算符可以使前面的函數成為表達式,加上后面()可立即執行。 //函數聲明無法立即執行一個函數,但是函數表達式可以 var a = function(){}();//這種是函數表達式,后面有()可以立即執行。成為一個立即執行函數。
var obj = { number: 3, xxx: (function () { console.log(this + "--")//立即執行函數中的this指向window,因為立即執行函數是window調用的 console.log(this.number + "~~~")//刪除上面一行,此處this.number返回undefined return function () { console.log(this.number + "】") this.number += 7; console.log(this + "+") } })() } obj.xxx() //相當于obj.xxx.call(),所以此處的this指向obj console.log(obj.number) //10
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102849.html
摘要:相信很多剛剛學習的新手都會有同感,當看一段代碼時,發現里面有很多,但是這些到底是指向哪里卻沒有那么清楚,為了搞清楚這些到底是什么情況,特地花點時間總結如下幾點最普遍的表示全局對象表示全局對象輸出為解析設置全局變量初始值為,當調用函數之后改變 相信很多剛剛學習js的新手都會有同感,當看一段js代碼時,發現里面有很多this,但是這些this到底是指向哪里卻沒有那么清楚,為了搞清楚這些th...
摘要:將作用域賦值給變量這里的作用域是,而不是將作用域賦值給一個變量閉包返回瀏覽器中內存泄漏問題大家都知道,閉包會使變量駐留在內存中,這也就導致了內存泄漏。 上一章我們講了匿名函數和閉包,這次我們來談談閉包中作用域this的問題。 大家都知道,this對象是在運行時基于函數的執行環境綁定的,如果this在全局就是[object window],如果在對象內部就是指向這個對象,而閉包卻是在運行...
摘要:工廠模式優點集中實例化,可以傳參等缺點分不清屬于哪個對象我們先來談談優點,看例子集中實例化返回實例化對象返回返回不難看出,工廠模式比上面的例子減少了很多代碼。 ECMAscript開發的兩種模式:1.過程化 2.OOP(面向對象) 面向對象的語言有一個標志,那就是類的概念,而通過類可以創建任意多個具有相同屬性的方法的對象。但是ECMAscript中沒有類的概念! 又談作用域 首先...
摘要:想要解決這樣的問題的話,可以借助構造函數也可以叫做偽造對象或經典繼承。這種方式實現非常簡單,就是在子對象的構造函數中調用父對象的構造函數。 原型式繼承 原型式繼承,就是一定一個函數,該函數中創建一個臨時性的構造函數,將作為參數,傳入的對象作為這個構造函數的原型,最后返回這個構造函數的實例對象 /*定義函數:用于實現對象之間的繼承 參數: obj:表示繼承關系中的父級對象...
摘要:對其的解釋為概述監視一個對象的某個屬性是否發生變化在該屬性變化時立即觸發指定的回調函數語法參數想要監視值是否發生變化的指定對象的某個屬性的屬性名稱當指定的屬性發生變化時執行的回調函數在內查看其聲明如下可以看到這兩個方法是只針對內核的瀏覽器使 MDN 對其的解釋為: 概述: 監視一個對象的某個屬性是否發生變化,在該屬性變化時立即觸發指定的回調函數. 語法: object....
閱讀 2892·2021-10-14 09:42
閱讀 1245·2021-09-24 10:32
閱讀 2953·2021-09-23 11:21
閱讀 2840·2021-08-27 13:10
閱讀 3327·2019-08-29 18:41
閱讀 2195·2019-08-29 15:16
閱讀 1195·2019-08-29 13:17
閱讀 893·2019-08-29 11:22