国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

js函數(shù)探索

thursday / 1096人閱讀

摘要:關(guān)于構(gòu)造函數(shù)有幾點需要特別注意構(gòu)造函數(shù)允許在運行時動態(tài)的創(chuàng)建并編譯函數(shù)。而函數(shù)本身的表示該函數(shù)的形參。每一個函數(shù)都包含不同的原型對象,當(dāng)將函數(shù)用作構(gòu)造函數(shù)的時候,新創(chuàng)建的對象會從原型對象上繼承屬性。

該文章以收錄: 《JavaScript深入探索之路》 前言

函數(shù)是這樣的一段JavaScript代碼,它只定義一次,但是可能被執(zhí)行或調(diào)用任意次。你可能已經(jīng)從諸如子例程或者過程這些名字里對函數(shù)的概念有所了解。 JavaScript函數(shù)時參數(shù)化的:函數(shù)的定義會包括一個稱為形參的表示符列表,這些參數(shù)在函數(shù)體中像局部變量一樣工作。函數(shù)調(diào)用會為形參提供實參的值,函數(shù)使用它們實參的值來計算返回值,成為該函數(shù)調(diào)用表達式的值。除了實參外,每次調(diào)用還會擁有另一個值 —— 本次調(diào)用的上下文 —— 這就是this關(guān)鍵字的值。

參數(shù)有形參(parameter)和實參(argument)的區(qū)別,形參相當(dāng)于函數(shù)中定義的變量,實參是運行時的函數(shù)調(diào)用時傳入的參數(shù)。

創(chuàng)建函數(shù)

一般我們有三種方法去創(chuàng)建函數(shù):

函數(shù)聲明:function foo(){}

函數(shù)表達式:var foo = function(){}

函數(shù)構(gòu)造法:var foo = new Function("a","b","return a+b")

函數(shù)聲明和函數(shù)表達式

1.什么是函數(shù)聲明,什么是函數(shù)表達式

ECMA規(guī)范說:函數(shù)聲明必須帶有標(biāo)示符(Identifier)(就是大家常說的函數(shù)名稱),而函數(shù)表達式則可以省略這個標(biāo)示符:

// 函數(shù)聲明
function 函數(shù)名(可選參數(shù)){}

// 函數(shù)表達式
function 可選函數(shù)名(可選參數(shù)){}

我們可以很清楚的看出,如果沒有標(biāo)識符(函數(shù)名),該函數(shù)就一定是函數(shù)表達式,如果有標(biāo)識符我們該怎么區(qū)分函數(shù)聲明和函數(shù)表達式呢。

函數(shù)聲明我們不用太多的考慮,很容易看出來,我們來看看函數(shù)表達式都有哪些自然就知道哪些是函數(shù)聲明了。

第一種函數(shù)表達式:var聲明的函數(shù)我們很常見

// 沒有標(biāo)識符一定是表達式
var fun = function(){}

//我們還可以這樣寫 

var fun = function foo(){}

第二種我們帶有標(biāo)識符,但將函數(shù)賦值給變量后,該函數(shù)就成了函數(shù)表達式。在這里foo標(biāo)識符在該函數(shù)體外訪問時并不起作用

var fun = function foo(a){
  
    if(a){
      console.log("外部調(diào)用了");  
      foo(false); //這會執(zhí)行函數(shù)fun。
    }else{
      console.log("內(nèi)部調(diào)用了");
    }

}

fun(true); //外部調(diào)用了 ,內(nèi)部調(diào)用了

foo(); // 報錯 ReferenceError: foo is not defined

我們可以看出,函數(shù)表達式中foo標(biāo)識符只能在函數(shù)內(nèi)部使用,去訪問該函數(shù),在函數(shù)外部訪問不到任何東西。上面我們加判斷是為了防止函數(shù)一直遞歸。

第二種函數(shù)表達式:()括號包住的函數(shù)

// 這是函數(shù)表達式
(function foo(){})

括號包住的函數(shù)是函數(shù)表達式是因為,()是一個分組操作符,分組操作符內(nèi)只能是表達式。

例如:

//Unexpected token var
(var a = 0) 

上面報錯,這是因為var是一個語句,而分組操作符內(nèi)只能是表達式。還有我們在使用evel()時這樣寫 var ev = eval("(" + json + ")") ,這里是強制將{}解析為表達式而不是代碼塊。

2.函數(shù)聲明和函數(shù)表達式的特點

函數(shù)聲明在我們的代碼執(zhí)行前,會被整個提升,也就是說我們在函數(shù)聲明之前就可以調(diào)用該函數(shù),而函數(shù)表達式不能夠被提升。

a() // 結(jié)果 我是函數(shù)a"
function a(){
    console.log("我是函數(shù)a");
}

fun() //結(jié)果 fun is not a function
var fun = function b(){
    console.log("我是函數(shù)b");
}

為什么會出現(xiàn)這種情況我們在以后的文章中會詳細的討論。同時,我們應(yīng)該養(yǎng)成一種習(xí)慣,盡量不要在函數(shù)聲明之前使用函數(shù)。這只是一種良好的代碼書寫習(xí)慣。

其次我們需要注意的是在if判斷語句中我們不應(yīng)該出現(xiàn)函數(shù)聲明,即便是沒有報錯,也是不推薦這樣去寫的。

立即執(zhí)行函數(shù)(表達式)和自執(zhí)行函數(shù)

1. 立即執(zhí)行函數(shù)(表達式)

我們來看一下:

(function (){
    console.log("one");
})();


(function (){
    console.log("two");

}());

上邊兩個函數(shù)都可以自己去執(zhí)行,而值有個共同的特點就是括號左邊的函數(shù)必須是一個函數(shù)表達式,而不是函數(shù)聲明。

// 如果括號左邊是函數(shù)聲明,報錯
function fun(){
    console.log()
}()



// 括號左邊是函數(shù)時表達式,(函數(shù)表達式都可以自執(zhí)行)

var F = function(){
    return 10;
}();

true && function (){}();

0 , function (){}();

//你甚至看還可以這樣

!function () { /* code */ } ();
~function () { /* code */ } ();
-function () { /* code */ } ();
+function () { /* code */ } ();

new function(){}();

其實上邊的些自執(zhí)行函數(shù)表達式我們?yōu)榱朔奖阄覀兊拈喿x我們一般會用到第一個和第二個,當(dāng)然如果你非要搞個性化,使用其他的也是可以。只不過你的代碼并不美觀,后期也不容易維護。

2. 什么是自執(zhí)行函數(shù),像這樣

function fun1(){
    //code
}
fun1();


function fun2(){
    fun2() // 遞歸
}

// 這是一個自執(zhí)行匿名函數(shù)
var foo = function () { arguments.callee(); };

看了這些例子,我們應(yīng)該清楚了什么是自執(zhí)行,什么是立即調(diào)用。

函數(shù)構(gòu)造器

Function()構(gòu)造函數(shù)并不需要通過傳入實參以指定函數(shù)名,就像函數(shù)直接量一樣,Function()構(gòu)造函數(shù)創(chuàng)建一個匿名函數(shù)。

關(guān)于Function()構(gòu)造函數(shù)有幾點需要特別注意

Function()構(gòu)造函數(shù)允許JavaScript在運行時動態(tài)的創(chuàng)建并編譯函數(shù)。

Function()構(gòu)造函數(shù)每次執(zhí)行時都會解析函數(shù)主體,并創(chuàng)建一個新的函數(shù)對象,所以當(dāng)在一個循環(huán)或頻繁執(zhí)行的函數(shù)中調(diào)用Function()構(gòu)造函數(shù)效率是非常低的。而函數(shù)字面量(函數(shù)表達式)卻不是每次遇到都會重新編譯的,用Function()構(gòu)造函數(shù)創(chuàng)建一個函數(shù)時并不遵循典型的作用域,它一直把它當(dāng)作是頂級函數(shù)來執(zhí)行

它所創(chuàng)建的函數(shù)并不是使用詞法作用域,相反,函數(shù)體代碼的編譯總是會在頂層函數(shù)執(zhí)行,

用函數(shù)構(gòu)造器創(chuàng)建的函數(shù)不會在上下文中創(chuàng)建閉包,它們總是被創(chuàng)建在全局作用域中,當(dāng)執(zhí)行被創(chuàng)建的函數(shù)時,它們只能使用自己的局部變量或者全局變量。例如下面:

var scop = "global";
function fun(){
    var scop  = "fun";
    return new Function("return scope") // global
}
函數(shù)的屬性、方法和構(gòu)造函數(shù)

1. length屬性

函數(shù)體中,arguments.length表示傳入函數(shù)的實參個數(shù)。而函數(shù)本身的length表示該函數(shù)的形參。

 function fun(x,y,z){
     console.log(arguments.length);// 2
     console.log(arguments.callee.length); //3
 }

 fun(1,2);

我們這里提一下,在函數(shù)中的arguments,函數(shù)中arguments包含所用實參,它并不是一個真正的數(shù)組,而是一個實參的對象。另外他還有兩個特別的屬性calleecaller屬性。

callee屬性只帶黨慶正在執(zhí)行的函數(shù)。
caller屬性時非標(biāo)準(zhǔn)的,但大多數(shù)瀏覽器都實現(xiàn)了這個屬性它指帶調(diào)用當(dāng)前正在執(zhí)行的函數(shù)的函數(shù)。

通過caller屬性可以訪問調(diào)用棧。callee屬性在某些時候會非常的有用,比如在匿名函數(shù)中通過callee來遞歸調(diào)用自身,上面我們已經(jīng)提到過。

2. prototype屬性

每一個函數(shù)都包含一個prototype屬性,這個屬性是指向一個對象的引用,這個對象稱作"原型對象"。每一個函數(shù)都包含不同的原型對象,當(dāng)將函數(shù)用作構(gòu)造函數(shù)的時候,新創(chuàng)建的對象會從原型對象上繼承屬性。

3. call()方法和apply()方法

call 和 apply 是為了改變某個函數(shù)運行時的 context 即上下文而存在的,換句話說,就是為了改變函數(shù)體內(nèi)部 this 的指向。因為 JavaScript 的函數(shù)存在「定義時上下文」和「運行時上下文」以及「上下文是可以改變的」這樣的概念。

它們的用法也是很簡單的。例如:

var obj = {
        msg:"我是obj對象",
    fun:function(){
       console.log(this.msg);
    },
}

var objTwo = {
    msg:"我是objTwo對象"
};

// 這里我們想讓通過objTwo 對象調(diào)用 obj對象的fun方法,
// 此時obj的fun方法中的this已經(jīng)改變了指向。
obj.fun.call(objTwo) // 我是objTwo對象

call 和 apply 的區(qū)別在于他們傳參的形式不同:

var obj = {
        msg:"我是obj對象",
    fun:function(one,two){
       console.log(this.msg);
       console.log("我是參數(shù):"+ one + "," +two);
    },
}

var objTwo = {
    msg:"我是objTwo對象"
};

// 這里我們想讓通過objTwo 對象調(diào)用 obj對象的fun方法,
// 此時obj的fun方法中的this已經(jīng)改變了指向。
obj.fun.call(objTwo,1,2) // 我是objTwo對象 ,我是參數(shù):1,2

obj.fun.apply(objTwo,[1,2]) // 我是objTwo對象 ,我是參數(shù):1,2

高階函數(shù)

所謂高階函數(shù)就是操作函數(shù)的函數(shù),它接收一個或多個函數(shù)作為參數(shù),并返回一個新函數(shù)。我們來看一個例子:

這個例子的主要作用是,fun函數(shù)接收f()g()兩個函數(shù),并返回一個新的函數(shù)用以計算f(g())

function fun(f,g){
    return function(){
      return f.call(this,g.apply(this,arguments));
    }
}

var square = function(x){
    return x * x
}

var sum = function(x,y){
    return x + y;
}

var suqareOfSum = compose(square,sum)

squareOfSum(2,3) // 25

在這里函數(shù)fun() 就是高階函數(shù)。

不完全函數(shù)

不完全函數(shù)是一種函數(shù)變換技巧,即把一次完整的函數(shù)調(diào)用折成多次函數(shù)調(diào)用,每次傳入的實參都是完整實參的一部分,每個拆分開的函數(shù)叫做不完全函數(shù),每次函數(shù)調(diào)用叫做不完全調(diào)用,這種函數(shù)變換的特點是每次調(diào)用都反一個函數(shù),知道得到最終運行結(jié)果為止,例如:將函數(shù)f(1,2,3,4,5)的調(diào)用修改為等價的f(1,2)(3,4)(5)后者包含三次調(diào)用,和每次調(diào)用相關(guān)的函數(shù)就是 不完全函數(shù)”。

結(jié)束

參考文獻: 《JavaScript權(quán)威指南》

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/89706.html

相關(guān)文章

  • javascript對象不完全探索記錄03:小伙子,你對象咋來的?上篇

    摘要:看著別人寫的功能對,就直接拿過來用,寫出來的代碼臃腫到爆炸,滿屏幕的的初級使用方式,運氣好了能湊合跑起來,出了問題全臉懵逼,心中安慰自己一萬遍我可是干設(shè)計的,但是既然打算好好整下就得從頭開始看了。 溫馨提示:作者的爬坑記錄,對你等大神完全沒有價值,別在我這浪費生命 首先,說實話,我對不起javascript,作為一個接觸前端快10年的老前端(偽),一直發(fā)揚的是不求甚解的拿來就用主義。看...

    Pluser 評論0 收藏0
  • React原理探索- @providesModule 模塊系統(tǒng)

    摘要:原理探索模塊系統(tǒng)是什么拋出組件化的概念后,對于開發(fā)者而言,為了提高代碼的可讀性與結(jié)構(gòu)性,通過文件目錄結(jié)構(gòu)去闡述組件嵌套關(guān)系無疑是一個很好的辦法,但是目錄級別的加深,同時讓的文件路徑讓人頭疼。 React原理探索- @providesModule 模塊系統(tǒng) @providesModule是什么 react拋出組件化的概念后,對于開發(fā)者而言,為了提高代碼的可讀性與結(jié)構(gòu)性,通過文件目錄結(jié)構(gòu)去...

    My_Oh_My 評論0 收藏0
  • javascript閉包不完全探索記錄02:閉包?干嘛使!

    摘要:溫馨提示作者的爬坑記錄,對你等大神完全沒有價值,別在我這浪費生命溫馨提示續(xù)本文將會成為一篇筆記類型的文章,記錄閉包具體的應(yīng)用方式溫馨提示再續(xù)本文存在錯誤,會慢慢改進的,請不要把我說的當(dāng)真在上一篇博文閉包不完全探索記錄閉包啥餡的中,對中 溫馨提示:作者的爬坑記錄,對你等大神完全沒有價值,別在我這浪費生命溫馨提示-續(xù):本文(maybe)將會成為一篇筆記類型的文章,記錄閉包具體的應(yīng)用方式溫馨...

    Render 評論0 收藏0
  • JavaScript模塊化編程探索

    摘要:模塊化編程,已經(jīng)成為一個迫切的需求。隨著網(wǎng)站功能逐漸豐富,網(wǎng)頁中的也變得越來越復(fù)雜和臃腫,原有通過標(biāo)簽來導(dǎo)入一個個的文件這種方式已經(jīng)不能滿足現(xiàn)在互聯(lián)網(wǎng)開發(fā)模式,我們需要團隊協(xié)作模塊復(fù)用單元測試等等一系列復(fù)雜的需求。 隨著網(wǎng)站逐漸變成互聯(lián)網(wǎng)應(yīng)用程序,嵌入網(wǎng)頁的Javascript代碼越來越龐大,越來越復(fù)雜。網(wǎng)頁越來越像桌面程序,需要一個團隊分工協(xié)作、進度管理、單元測試等等......開發(fā)...

    jayzou 評論0 收藏0
  • 探索Javascript 異步編程

    摘要:因為瀏覽器環(huán)境里是單線程的,所以異步編程在前端領(lǐng)域尤為重要。除此之外,它還有兩個特性,使它可以作為異步編程的完整解決方案函數(shù)體內(nèi)外的數(shù)據(jù)交換和錯誤處理機制。 showImg(https://segmentfault.com/img/bVz9Cy); 在我們?nèi)粘>幋a中,需要異步的場景很多,比如讀取文件內(nèi)容、獲取遠程數(shù)據(jù)、發(fā)送數(shù)據(jù)到服務(wù)端等。因為瀏覽器環(huán)境里Javascript是單線程的,...

    Salamander 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<