摘要:不過,匿名函數的執行環境具有全局性,因此其通常指向。可行原因是這里的賦值實際上把匿名函數當作表達式處理了,表達式后面可以加括號。
this是Javascript語言的一個關鍵字。
它代表函數運行時,自動生成的一個內部對象,只能在函數內部使用。比如,
function test(){
this.x = 1;
}
隨著函數使用場合的不同,this的值會發生變化。
有一個總的原則,那就是this指的是,調用函數的那個對象。
下面分四種情況,詳細討論this的用法:
情況一:純粹的函數調用
這是函數的最通常用法,屬于全局性調用,因此this就代表全局對象Global。
1)請看下面這段代碼,它的運行結果是1。
function test(){ this.x = 1; alert(this.x); } test(); // 1
為了證明this就是全局對象,我對代碼做一些改變:
var x = 1; function test(){ alert(this.x); } test(); // 1
運行結果還是1。再變一下:
var x = 1; function test(){ this.x = 0; } test(); alert(x); //0
2)接下來分析匿名函數下的情況(博客內容外的自添加):
var name="the window"; var object={ name:"My object", getNameFunc:function(){ return function(){ return this.name; //沒有被直接調用,此匿名函數的執行環境具有全局性 }; } }; alert(object.getNameFunc()());//the window(非嚴格模式下)
情況二:作為對象方法的調用
函數還可以作為某個對象的方法調用,這時this就指這個上級對象。
function test(){ alert(this.x); } var o = {}; o.x = 1; o.m = test; o.m(); // 1
情況三 作為構造函數調用
所謂構造函數,就是通過這個函數生成一個新對象(object)。這時,this就指這個新對象。
function test(){ this.x = 1; } var o = new test(); alert(o.x); // 1
運行結果為1。為了表明這時this不是全局對象,我對代碼做一些改變:
var x = 2; function test(){ this.x = 1; } var o = new test(); alert(x); //2
運行結果為2,表明全局變量x的值根本沒變。
情況四 apply調用
apply()是函數對象的一個方法,它的作用是改變函數的調用對象,它的第一個參數就表示改變后的調用這個函數的對象。因此,this指的就是這第一個參數。
var x = 0; function test(){ alert(this.x); } var o={}; o.x = 1; o.m = test; o.m.apply(); //0
apply()的參數為空時,默認調用全局對象。因此,這時的運行結果為0,證明this指的是全局對象。
如果把最后一行代碼修改為
o.m.apply(o); //1
運行結果就變成了1,證明了這時this代表的是對象o。
----------摘自阮一峰博客
另附筆者見解:
This對象是在運行時基于函數的執行環境綁定的:在全局函數中,this等于window,而當函數作為某個對象的方法調用時,this等于那個對象。不過,匿名函數的執行環境具有全局性,因此其this通常指向window。但是由于閉包編寫方式不同,結果沒有那么明顯。
別忘了:有一個總的原則,那就是this指的是,調用函數的那個對象。
例1. 匿名函數沒有被直接調用,匿名函數的執行環境具有全局性,this指的是window對象 var name="the window"; var object={ name:"My object", getNameFunc:function(){ return function(){ return this.name; };//沒有被直接調用,此匿名函數的執行環境具有全局性 } }; alert(object.getNameFunc()());//the window(非嚴格模式下)
例2.匿名函數被直接調用,this指的是調用它的對象
var name="the window"; var object={ name:"My object", getNameFunc:function(){ return this.name; };//被getNameFunc(也就是object)調用 } }; alert(object.getNameFunc()());//My object(非嚴格模式下)
例3.通過that綁定執行環境對象(this是關鍵字,而that不是關鍵字)
var name="the window"; var object={ name:"My object", getNameFunc:function(){ var that=this;//通過that綁定了object對象 ;object <--getNameFunc(name) return function(){ return that.name;//創建閉包,返回that.name };//object下的name } }; alert(object.getNameFunc()());//My object(非嚴格模式下)
模仿塊級作用域(私有作用域):
語法如下:
(function(){ //這里是塊級作用域 })();
以上代碼定義并且立即調用了一個匿名函數。將函數聲明包含在一對圓括號中,表示它實際上是一個函數表達式。而緊隨其后的另一對括號會立即調用這個函數。
類似于:
var someFunction=function(){ //這里是塊級及作用域 }; someFunction();
這里定義了一個函數(匿名函數,并把值賦給someFunction)然后立即調用了它(在函數名稱后面添加一對括號)。
下面來看另一種不加括號的情況:
function(){//dosomething}(); 例:function (){alert("Hi")}();
這段代碼會導致語法錯誤,是因為javascript將function關鍵字當作一個函數聲明的開始,而函數聲明后面不能跟圓括號。而表達式后面可以跟圓括號,要將函數聲明變成表達式,只要向下面那樣給它加一對圓括號即可:
(function(){ //這里是塊及作用域 })(); 如:(function (){alert("Hi")}());
注:
1.result=function(){//dosomething}(); 這個匿名函數后加括號不會報錯而且匿名函數會立即執行。 2.result=function(){//dosomething}()與function(){//dosomething}()兩個語句完全不同,前者是有賦值的。 3.可行原因是這里的賦值js實際上把匿名函數當作表達式處理了,表達式后面可以加括號。 而且在function(){//dosomething}()前面加“-“、”!“等運算符還會根據運算規則改變賦給result的值。 4.result=
function(){//dosomething}();
2.!function(){ // do something }();
3.~ function() {}();
4.+ function() {}();
5.- function() {}()
原理是語句function(){//dosomething}()都被當作表達式處理了(賦值前計算表達式的值),就是2、3、4、5例可以自執行,自執行的原因也是function(){//dosomething}()由于前面的符號被當作表達式處理了
。
私有作用域實例:
function outputNumbers(count){ (function(){ for(var i=0;i面試題解析:
1. var foo = { bar: function() { return this.baz; }, baz: 1 }; (function(){ return typeof arguments[0](); })(foo.bar); 答案:"undefined"在arguments[0]()中執行了一個方法,arguments[0]就是foo.bar方法
注意: foo.bar作為整體傳入函數中,但是foo.bar中的this是沒有綁定到foo,雖然 foo.bar 傳遞給了函數,但是真正執行的時候,函數 bar 的上下文環境是 arguments ,并不是 foo。(foo.bar作為整體的傳遞方式解除了foo對bar的調用作用)arguemnts[0] 可以理解為 arguments.0(不過寫代碼就不要這樣了,語法會錯誤的),所以這樣看來,上下文環境是 arguemnts 就沒問題了,所以在執行baz的時候自然this就是window了,window 上沒有baz屬性,返回的就是undefined, typeof調用的話就轉換成"undefined"了
這里的 this 指的是 arguments,經測試確實如此: 2. var foo = { bar: function(){ return this.baz; }, baz: 1 } typeof (f = foo.bar)(); 答案:"undefined" 類似于 var foo = { bar: function(){ return this.baz; }, baz: 1 } f = foo.bar; typeof f(); 把foo.bar存儲給f然后調用,所以this在foo.bar引用的是全局對象,所以就沒有baz屬性了 換句話說:foo.bar執行的時候上下文是 foo,但是當 把 foo.bar 賦值給 f 的時候,f 的上下文環境是 window ,是沒有 baz 的,所以是 ”undefined"。解決方案:利用閉包或者bind()
//函數綁定bind() function bind(fn,context){//返回閉包 return function(){ return fn.apply(context,arguments);//arguments指函數內部的而非bind的 } } //測試 var handler={ message : "Event Handler", handleClick : function(event){ alert(this.message); } } //var documentFragment=document.createDocumentFragment(); var text=""; document.body.innerHTML=text; var btn=document.getElementsByTagName("button")[0]; EventUtil.addHandler(btn,"click",bind(handler.handleClick,handler));
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79463.html
摘要:赫敏第三行的是在最外層執行,也就是在全局對象下。而在對象下聲明了屬性,就相當于羅恩,輸出的當然就是羅恩。之所以寫這篇文章,是為了我下一篇文章做鋪墊快速理解中和的用法敬請期待 this是 JS 這門語言的魅力之一——靈活方便又難以捉摸,即使是有經驗的程序員,如果不仔細也有可能搞錯,關于this的用法也成為許多公司的經典面試題。 如果你寫過 Java ,你可能接觸過this——一般指向當前...
摘要:其實它們都很簡單,但是在處理一些與相關的函數的時候,用來改變函數中的指向,卻是必不可少的工具,所以必須掌握好它們的用法。 關于javascript中的bind、call、apply等函數的用法 我GitHub上的菜鳥倉庫地址: 點擊跳轉查看其他相關文章 文章在我的博客上的地址: 點擊跳轉 ? ? ? ? 前面的文章已經說到this的指向了,那么這篇文章就要說一說和this相關的三個...
摘要:什么是函數的作用域函數作用域在中,作用域為可訪問變量,對象,函數的集合。函數作用域作用域在函數內修改。與函數又有什么關系呢對象是在運行時基于函數的執行環境綁定的。 什么是函數的作用域 函數作用域:在 JavaScript 中,作用域為可訪問變量,對象,函數的集合。JavaScript 函數作用域: 作用域在函數內修改。 this 與函數又有什么關系呢? this對象是在運行時基于函數的...
摘要:使用原型屬性屬性允許您向對象構造函數添加新屬性屬性還允許您向對象構造函數添加新方法更好的原型對象的教程 JavaScript對象原型所有JavaScript對象都從原型繼承屬性和方法。 js JavaScript 對象 function Person(first, last, age, eye) { this.firstName = fi...
閱讀 1342·2021-09-24 10:26
閱讀 3655·2021-09-06 15:02
閱讀 605·2019-08-30 14:18
閱讀 577·2019-08-30 12:44
閱讀 3119·2019-08-30 10:48
閱讀 1936·2019-08-29 13:09
閱讀 1994·2019-08-29 11:30
閱讀 2279·2019-08-26 13:36