Javascript函數(shù)全解析

1.函數(shù)的聲明定義

兩種方式:

函數(shù)聲明語句

function foo1(args){
var x = 'hello';
}

函數(shù)表達(dá)式

var foo2 = function(args){ var x = 'hello'  };

兩種的區(qū)別:
第一種办绝,函數(shù)的定義會(huì)在執(zhí)行上下文開始執(zhí)行代碼之前被提升积蜻,通俗的講院崇,就是在函數(shù)聲明語句之前就可以調(diào)用函數(shù)了摔寨。
第二種迈着,在執(zhí)行上下文開始執(zhí)行代碼之前嬉橙,只有變量foo2會(huì)被提升,變量的初始化還在原來代碼的位置寥假,所以在函數(shù)表達(dá)式之前,foo2的值為undefined霞扬。
函數(shù)聲明和定義可以嵌套到其他函數(shù)里

2.函數(shù)調(diào)用

函數(shù)聲明的調(diào)用foo1() //這種是作為函數(shù)調(diào)用
作為方法屬性調(diào)用 obj.foo() //這種是作為方法調(diào)用
構(gòu)造函數(shù)調(diào)用 new Foo() //用于新建對(duì)象

三種的區(qū)別:

以函數(shù)調(diào)用形式調(diào)用的函數(shù)其this的值為全局對(duì)象(非嚴(yán)格)或者undefined(嚴(yán)格模式)糕韧,不管這個(gè)函數(shù)聲明在其他函數(shù)里還是在其他地方

以方法形式調(diào)用的函數(shù)其this的值為調(diào)用它的對(duì)象

function foo1(){
console.log(this);
foo2();
function foo2(){
console.log(this)
} 
}
var obj ={name : "obj", foo : foo1};
obj.foo();   //結(jié)果輸出為{name: "obj", foo: ?}  和window
//直接在瀏覽器的控制臺(tái)粘貼這段代碼看結(jié)果

將foo2的函數(shù)聲明變?yōu)楹瘮?shù)表達(dá)式再試試

function foo1(){
console.log(this);
var foo2 = function (){
console.log(this)
} 
foo2();            //這里輸出的this為什么為window??????
}
var obj ={name : "obj", foo : foo1};
obj.foo();
//對(duì)于foo2為什么輸出的是window我也很疑惑,函數(shù)表達(dá)式調(diào)用其實(shí)是看作方法調(diào)用的喻圃,
//所以foo2里的this應(yīng)該是調(diào)用它的作用域的變量對(duì)象萤彩,很疑惑

構(gòu)造函數(shù)調(diào)用
構(gòu)造函數(shù)調(diào)用創(chuàng)建一個(gè)新的空對(duì)象,這個(gè)對(duì)象繼承自構(gòu)造函數(shù)的prototype屬性斧拍,構(gòu)造函數(shù)可以初始化這個(gè)新的對(duì)象雀扶,并將這個(gè)對(duì)象作為其的調(diào)用上下文(this),可以用this引用新創(chuàng)建的對(duì)象肆汹。如 new o.m();中愚墓,m調(diào)用的上下文不是o。//一般不這么用
構(gòu)造函數(shù)一般沒有返回值昂勉,不過如果顯式地返回一 個(gè)對(duì)象浪册,則這個(gè)調(diào)用表達(dá)式的值就是這個(gè)對(duì)象 // 一般不這么用

3.函數(shù)的作用域(鏈)

函數(shù)的作用域鏈在函數(shù)聲明定義的時(shí)候就已確定了(這里很難講清楚,應(yīng)該說是在聲明定義時(shí)確定了一條作用域鏈岗照,這個(gè)作用域鏈不包括函數(shù)本身的作用域村象,只有在函數(shù)被調(diào)用時(shí),函數(shù)本身的作用域才加入到其作用域鏈頂部)攒至。

不管函數(shù)在哪里被調(diào)用厚者,它的作用域鏈在定義時(shí)就被確定了,作用域鏈只和函數(shù)被定義的地方有關(guān)迫吐。

對(duì)于作為對(duì)象方法的函數(shù)的作用域:
var obj = {name : 'obj' ,
           foo : function(args){ console.log(name)} ,
           callfoo : function(){ obj.foo();} 
};
var name = 'scope';
function outterFoo(){ console.log(name)};
obj.foo();
outterFoo();
obj.callfoo();
//輸出的結(jié)果都為scope

作為對(duì)象方法的函數(shù)的作用域鏈(未被調(diào)用前)和與對(duì)象在同一層的函數(shù)的作用域鏈?zhǔn)且粯拥摹?/p>

4.函數(shù)的執(zhí)行上下文

在打開頁面時(shí)库菲,全局執(zhí)行上下文就被壓入執(zhí)行上下文棧中,當(dāng)調(diào)用函數(shù)時(shí)會(huì)將向執(zhí)行上下文中壓入函數(shù)的執(zhí)行上下文渠抹,在函數(shù)中如果調(diào)用其它函數(shù)則繼續(xù)壓入新的執(zhí)行上下文蝙昙,函數(shù)執(zhí)行完之后闪萄,其執(zhí)行上下文被彈出棧。

之后會(huì)寫文章從內(nèi)存的角度來分析函數(shù)的執(zhí)行上下文奇颠。持續(xù)關(guān)注

5.函數(shù)里變量的查找

函數(shù)里變量的查找是在作用域鏈上依次查找的败去,會(huì)一層一層向外查找。變量的查找不同于this的屬性的查找

this和作用域是兩個(gè)完全不同的概念 this是javascript的關(guān)鍵字而不是變量烈拒。

6.函數(shù)的this

this也可以叫做調(diào)用上下文(和執(zhí)行上下文有區(qū)別) // 個(gè)人見解

在不指定的情況下圆裕,this指向的是調(diào)用該方法的對(duì)象。
this上屬性的查找是在對(duì)象的原型鏈上查找的
在構(gòu)造函數(shù)中荆几,this指向的是通過new關(guān)鍵字新建的實(shí)例對(duì)象

可以指定this屬性的指向
利用call apply bind 三個(gè)函數(shù)
function foo(arg1,arg2,arg3){};

foo.call{obj,arg1,arg2...}  //call指定this為obj吓妆,后面的參數(shù)作為foo的參數(shù)傳進(jìn)去
foo.apply{obj,[arg1,arg2]}  //也是制定this為obj,但是傳給foo的參數(shù)是以數(shù)組的形式
var newfoo = foo.bind(obj,arg1,arg2)  // 為foo綁定this吨铸,和兩個(gè)參數(shù)    bind返回的是一個(gè)新函數(shù)

調(diào)用新的函數(shù)行拢,會(huì)調(diào)用foo,而且foo的this都是指向obj诞吱,而且傳入newfoo的參數(shù)都作為參數(shù)賦值給arg3及后面的參數(shù)舟奠,因?yàn)閍rg1,arg2已經(jīng)被綁定了。

//模擬bind , bind的一些特性還是模擬不來房维,功能可以模擬
Function.prototype.bind = Function.prototype.bind || function(obj...){
var self = this;
var boundArgs = arguments;
return function(){
var args=[],i;
for(i=1;i<boundArgs.length;i++) args.push(boundArgs[i]);
for(i=0;i<arguments.length;i++) args.push(arguments[i]);
return self.apply(obj,args);
}
};

7.自定義函數(shù)屬性

函數(shù)也是一種特殊的對(duì)象沼瘫,可以為其自定義屬性。
function foo(){console.log(foo.counter++)};
foo.counter = 0;
這種做法有個(gè)問題咙俩,函數(shù)的counter屬性可以被隨性修改耿戚,可以利用閉包將屬性私有化。

通過給構(gòu)造函數(shù)添加方法和屬性就模擬實(shí)現(xiàn)了類方法和類字段

8.閉包

一句話理解閉包阿趁,局部作用域的變量被外部引用時(shí)膜蛔,其內(nèi)存空間不會(huì)被銷毀 (本人愚見,歡迎各路大神指正)

var unique = (function(){
                  var counter = 0; 
                  return function(){ return counter++}}());   //閉包的典型例子
//函數(shù)每次調(diào)用時(shí)在內(nèi)存中創(chuàng)建的空間是不一樣的歌焦。
function getUniqueFoo(){
var counter = 0; 
return function(){ return counter++}   //這里返回的函數(shù)里存在外層函數(shù)的局部變量counter
}
var unique2 = getUniqueFoo();   //unique2指向返回的函數(shù)
var unique3 = geUniqueFoo();    //unique2和unique3是互不干擾的飞几,因?yàn)閮?nèi)存空間不是同一塊
//又一個(gè)閉包例子
function getApp(){
var appName = "xxx";
var version = "1.xxx";
var setName = function(name){
appName = name;
}
return {
get app(){ return appName},  //存取器屬性
version : version, 
setName : setName,
}
}
var App =getApp();

可以在外部函數(shù)將this轉(zhuǎn)存為一個(gè)變量,以便在閉包中訪問,外部函數(shù)的arguments 也一樣
arguments是函數(shù)的類數(shù)組對(duì)象
arguments.callee 指向的是arguments所在的函數(shù)本身

之后會(huì)寫文章從內(nèi)存的角度來分析函數(shù)的閉包独撇。持續(xù)關(guān)注

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末屑墨,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子纷铣,更是在濱河造成了極大的恐慌卵史,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件搜立,死亡現(xiàn)場離奇詭異以躯,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門忧设,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刁标,“玉大人,你說我怎么就攤上這事址晕“蛐福” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵谨垃,是天一觀的道長启搂。 經(jīng)常有香客問我,道長刘陶,這世上最難降的妖魔是什么胳赌? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮匙隔,結(jié)果婚禮上疑苫,老公的妹妹穿的比我還像新娘。我一直安慰自己纷责,他們只是感情好缀匕,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著碰逸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪阔加。 梳的紋絲不亂的頭發(fā)上饵史,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音胜榔,去河邊找鬼胳喷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛夭织,可吹牛的內(nèi)容都是我干的吭露。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼尊惰,長吁一口氣:“原來是場噩夢啊……” “哼讲竿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起弄屡,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤题禀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后膀捷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體迈嘹,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了秀仲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片融痛。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖神僵,靈堂內(nèi)的尸體忽然破棺而出雁刷,到底是詐尸還是另有隱情,我是刑警寧澤挑豌,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布安券,位于F島的核電站,受9級(jí)特大地震影響氓英,放射性物質(zhì)發(fā)生泄漏侯勉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一铝阐、第九天 我趴在偏房一處隱蔽的房頂上張望址貌。 院中可真熱鬧,春花似錦徘键、人聲如沸练对。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽螟凭。三九已至,卻和暖如春它呀,著一層夾襖步出監(jiān)牢的瞬間螺男,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工纵穿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留下隧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓谓媒,卻偏偏與公主長得像淆院,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子句惯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 原文:http://dmitrysoshnikov.com/ecmascript/javascript-the-c...
    jaysoul閱讀 473評(píng)論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理土辩,服務(wù)發(fā)現(xiàn),斷路器抢野,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • 作者:Dmitry A. Soshnikov編譯地址:http://dmitrysoshnikov.com/ecm...
    IT程序獅閱讀 3,333評(píng)論 2 12
  • 來源:仗劍走天涯! 關(guān)于javascript的作用域的一些總結(jié),主要參考以上文章,加上自己的整理的理解逝嚎。 近日對(duì)j...
    Michael_林閱讀 919評(píng)論 0 1
  • 繼承 一扁瓢、混入式繼承 二、原型繼承 利用原型中的成員可以被和其相關(guān)的對(duì)象共享這一特性补君,可以實(shí)現(xiàn)繼承引几,這種實(shí)現(xiàn)繼承的...
    magic_pill閱讀 1,050評(píng)論 0 3