欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Javascript函數(shù)聲明與遞歸調(diào)用

 更新時間:2016年10月22日 11:52:20   作者:con  
本篇文章詳細(xì)的介紹了Javascript函數(shù)聲明與遞歸調(diào)用,是JS入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下。

Javascript的函數(shù)的聲明方式和調(diào)用方式已經(jīng)是令人厭倦的老生常談了,但有些東西就是這樣的,你來說一遍然后我再說一遍。每次看到書上或博客里寫的Javascript函數(shù)有四種調(diào)用方式,我就會想起孔乙己:茴字有四種寫法,你造嗎?

盡管缺陷有一堆,但Javascript還是令人著迷的。Javascript眾多優(yōu)美的特性的核心,是作為頂級對象(first-class objects)的函數(shù)。函數(shù)就像其他普通對象一樣被創(chuàng)建、被分配給變量、作為參數(shù)被傳遞、作為返回值以及持有屬性和方法。函數(shù)作為頂級對象,賦予了Javascript強大的函數(shù)式編程能力,也帶來了不太容易控制的靈活性。

1、函數(shù)聲明

變量式聲明先創(chuàng)建一個匿名函數(shù),然后把它賦值給一個指定的變量:

var f = function () { // function body }; 

通常我們不必關(guān)心等號右邊表達式的作用域是全局還是某個閉包內(nèi),因為它只能通過等號左邊的變量f來引用,應(yīng)該關(guān)注的是變量f的作用域。如果f指向函數(shù)的引用被破壞(f = null),且函數(shù)沒有被賦值給任何其它變量或?qū)ο髮傩?,匿名函?shù)會因為失去所有引用而被垃圾回收機制銷毀。

也可以使用函數(shù)表達式創(chuàng)建函數(shù):

function f() { // function body } 

與變量式不同的是,這種聲明方式會為函數(shù)的一個內(nèi)置屬性name賦值。同時把函數(shù)賦值給當(dāng)前作用域的一個同名變量。(函數(shù)的name屬性,configurable、enumerable和writable均為false)

function f() { // function body } 
console.log(f.name); // "f" 
console.log(f); // f() 

Javascript變量有一個的特別之處,就是會把變量的聲明提前,表達式式的函數(shù)聲明,也會把整個函數(shù)的定義前置,因此你可以在函數(shù)定義之前使用它:

console.log(f.name); // "f" 
console.log(f); // f() 
function f() { // function body } 

函數(shù)表達式的聲明會被提升到作用域頂層,試試下面的代碼,它們不是本文的重點:

var a = 0; 
console.log(a); // 0 or a()? 
function a () {} 

Crockford建議永遠(yuǎn)使用第一種方式聲明函數(shù),他認(rèn)為第二種方式放寬了函數(shù)必須先聲明后使用的要求從而會導(dǎo)致混亂。(Crockford是一個類似于羅素口中用來比喻維特根斯坦的"有良心的藝術(shù)家"那樣的"有良心的程序員",這句話很拗口吧)

函數(shù)式聲明

function f() {} 

看起來是

var f = function f(){}; 

的簡寫。而

var a = function b(){}; 

的表達式,創(chuàng)建一個函數(shù)并把內(nèi)置的name屬性賦值為"b",然后把這個函數(shù)賦值給變量a,你可以在外部使用a()來調(diào)用它,但卻不能使用b(),因為函數(shù)已被賦值給a,所以不會再自動創(chuàng)建一個變量b,除非你使用var b = a聲明一個變量b。當(dāng)然這個函數(shù)的name是"b"而不是"a"。

使用Function構(gòu)造函數(shù)也可用來創(chuàng)建函數(shù):

var f = new Function("a,b,c","return a+b+c;"); 

這種方式其實是在全局作用域內(nèi)生成一個匿名函數(shù),并把它賦值給變量f。

2、遞歸調(diào)用

遞歸被用來簡化許多問題,這需要在一個函數(shù)體中調(diào)用它自己:

// 一個簡單的階乘函數(shù) 
var f = function (x) { 
  if (x === 1) { 
    return 1; 
  } else { 
    return x * f(x - 1); 
  } 
}; 

Javascript中函數(shù)的巨大靈活性,導(dǎo)致在遞歸時使用函數(shù)名遇到困難,對于上面的變量式聲明,f是一個變量,所以它的值很容易被替換:

var fn = f; 
f = function () {}; 

函數(shù)是個值,它被賦給fn,我們期待使用fn(5)可以計算出一個數(shù)值,但是由于函數(shù)內(nèi)部依然引用的是變量f,于是它不能正常工作了。

函數(shù)式的聲明看起來好些,但很可惜:

function f(x) { 
  if (x === 1) { 
    return 1; 
  } else { 
    return x * f(x - 1); 
  } 
} 
var fn = f; 
f = function () {}; // may been warning by browser 
fn(5); // NaN 

看起來,一旦我們定義了一個遞歸函數(shù),便須注意不要輕易改變變量的名字。

上面談?wù)摰亩际呛瘮?shù)式調(diào)用,函數(shù)還有其它調(diào)用方式,比如當(dāng)作對象方法調(diào)用。

我們常常這樣聲明對象:

var obj1 = { 
  num : 5, 
  fac : function (x) { 
    // function body 
  } 
}; 

聲明一個匿名函數(shù)并把它賦值給對象的屬性(fac)。

如果我們想要在這里寫一個遞歸,就要引用屬性本身:

var obj1 = { 
  num : 5, 
  fac : function (x) { 
    if (x === 1) { 
      return 1; 
    } else { 
      return x * obj1.fac(x - 1); 
    } 
  } 
}; 

當(dāng)然,它也會遭遇和函數(shù)調(diào)用方式一樣的問題:

var obj2 = {fac: obj1.fac}; 
obj1 = {}; 
obj2.fac(5); // Sadness 

方法被賦值給obj2的fac屬性后,內(nèi)部依然要引用obj1.fac,于是…失敗了。

換一種方式會有所改進:

var obj1 = { 
   num : 5, 
   fac : function (x) { 
    if (x === 1) { 
      return 1; 
    } else { 
      return x * this.fac(x - 1); 
    } 
  } 
}; 
var obj2 = {fac: obj1.fac}; 
obj1 = {}; 
obj2.fac(5); // ok 

通過this關(guān)鍵字獲取函數(shù)執(zhí)行時的context中的屬性,這樣執(zhí)行obj2.fac時,函數(shù)內(nèi)部便會引用obj2的fac屬性。

可是函數(shù)還可以被任意修改context來調(diào)用,那就是萬能的call和apply:

obj3 = {}; 
obj1.fac.call(obj3, 5); // dead again 

于是遞歸函數(shù)又不能正常工作了。

我們應(yīng)該試著解決這種問題,還記得前面提到的一種函數(shù)聲明的方式嗎?

var a = function b(){}; 

這種聲明方式叫做內(nèi)聯(lián)函數(shù)(inline function),雖然在函數(shù)外沒有聲明變量b,但是在函數(shù)內(nèi)部,是可以使用b()來調(diào)用自己的,于是

var fn = function f(x) { 
  // try if you write "var f = 0;" here 
  if (x === 1) { 
    return 1; 
  } else { 
    return x * f(x - 1); 
  } 
}; 
var fn2 = fn; 
fn = null; 
fn2(5); // OK 
 // here show the difference between "var f = function f() {}" and "function f() {}" 
var f = function f(x) { 
  if (x === 1) { 
    return 1; 
  } else { 
    return x * f(x - 1); 
  } 
}; 
var fn2 = f; 
f = null; 
fn2(5); // OK 
var obj1 = { 
  num : 5, 
  fac : function f(x) { 
    if (x === 1) { 
      return 1; 
    } else { 
      return x * f(x - 1); 
    } 
  } 
}; 
var obj2 = {fac: obj1.fac}; 
obj1 = {}; 
obj2.fac(5); // ok 
 
var obj3 = {}; 
obj1.fac.call(obj3, 5); // ok 

就這樣,我們有了一個可以在內(nèi)部使用的名字,而不用擔(dān)心遞歸函數(shù)被賦值給誰以及以何種方式被調(diào)用。

Javascript函數(shù)內(nèi)部的arguments對象,有一個callee屬性,指向的是函數(shù)本身。因此也可以使用arguments.callee在內(nèi)部調(diào)用函數(shù):

function f(x) { 
  if (x === 1) { 
    return 1; 
  } else { 
    return x * arguments.callee(x - 1); 
  } 
} 

但arguments.callee是一個已經(jīng)準(zhǔn)備被棄用的屬性,很可能會在未來的ECMAscript版本中消失,在ECMAscript 5中"use strict"時,不能使用arguments.callee。

最后一個建議是:如果要聲明一個遞歸函數(shù),請慎用new Function這種方式,F(xiàn)unction構(gòu)造函數(shù)創(chuàng)建的函數(shù)在每次被調(diào)用時,都會重新編譯出一個函數(shù),遞歸調(diào)用會引發(fā)性能問題——你會發(fā)現(xiàn)你的內(nèi)存很快就被耗光了。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 關(guān)于JavaScript 原型鏈的一點個人理解

    關(guān)于JavaScript 原型鏈的一點個人理解

    本文給大家分享的是個人關(guān)于JavaScript原型鏈相關(guān)知識的一些理解,這里推薦給大家,希望大家能夠喜歡
    2016-07-07
  • JavaScript數(shù)值類型知識匯總

    JavaScript數(shù)值類型知識匯總

    這篇文章主要給大家介紹了關(guān)于JavaScript數(shù)值類型知識匯總的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用JavaScript具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • 疊加計算出錯的解決方法

    疊加計算出錯的解決方法

    疊加計算出錯的解決方法...
    2007-01-01
  • 淺析JavaScript 箭頭函數(shù) generator Date JSON

    淺析JavaScript 箭頭函數(shù) generator Date JSON

    下面小編就為大家?guī)硪黄獪\析JavaScript 箭頭函數(shù) generator Date JSON。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-05-05
  • 關(guān)于JavaScript的變量的數(shù)據(jù)類型的判斷方法

    關(guān)于JavaScript的變量的數(shù)據(jù)類型的判斷方法

    這篇文章主要介紹了關(guān)于JavaScript的變量的數(shù)據(jù)類型的判斷方法,JS是一種弱類型語言,其數(shù)據(jù)類型的相關(guān)特性有時也受到不少開發(fā)者的詬病,需要的朋友可以參考下
    2015-08-08
  • javascript七大數(shù)據(jù)類型詳解

    javascript七大數(shù)據(jù)類型詳解

    這篇文章主要為大家介紹了 javascript七大數(shù)據(jù)類型,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • Javascript實例項目放大鏡特效的實現(xiàn)流程

    Javascript實例項目放大鏡特效的實現(xiàn)流程

    商城網(wǎng)站包括APP端中把鼠標(biāo)光標(biāo)移動到預(yù)覽圖上就會看到這部分商品圖片放大了,這就是JavaScript實現(xiàn)的放大鏡特效,今天我們也來實現(xiàn)一波
    2021-11-11
  • javascript 學(xué)習(xí)之旅 (1)

    javascript 學(xué)習(xí)之旅 (1)

    最近在看《JavaScript DOM 編程藝術(shù)》, 在此做下筆記。
    2009-02-02
  • 簡介JavaScript中POSITIVE_INFINITY值的使用

    簡介JavaScript中POSITIVE_INFINITY值的使用

    這篇文章主要介紹了簡介JavaScript中POSITIVE_INFINITY值的使用,是JS入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-06-06
  • 詳解在網(wǎng)頁上通過JS實現(xiàn)文本的語音朗讀

    詳解在網(wǎng)頁上通過JS實現(xiàn)文本的語音朗讀

    這篇文章主要介紹了在網(wǎng)頁上通過JS實現(xiàn)文本的語音朗讀,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03

最新評論