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

跟我學(xué)習(xí)javascript的函數(shù)和函數(shù)表達(dá)式

 更新時(shí)間:2015年11月16日 11:00:16   作者:小平果118  
跟我學(xué)習(xí)javascript的函數(shù)和函數(shù)表達(dá)式,詳細(xì)介紹了函數(shù)表達(dá)式、命名函數(shù)表達(dá)式的方法,感興趣的小伙伴們可以參考一下

1、函數(shù)聲明與函數(shù)表達(dá)式

在ECMAScript中,創(chuàng)建函數(shù)的最常用的兩個(gè)方法是函數(shù)表達(dá)式和函數(shù)聲明,兩者期間的區(qū)別是有點(diǎn)暈,因?yàn)镋CMA規(guī)范只明確了一點(diǎn):函數(shù)聲明必須帶有標(biāo)示符(Identifier)(就是大家常說(shuō)的函數(shù)名稱),而函數(shù)表達(dá)式則可以省略這個(gè)標(biāo)示符:

函數(shù)聲明:function 函數(shù)名稱 (參數(shù):可選){ 函數(shù)體 }

函數(shù)表達(dá)式:function 函數(shù)名稱(可選)(參數(shù):可選){ 函數(shù)體 }

所以,可以看出,如果不聲明函數(shù)名稱,它肯定是表達(dá)式,可如果聲明了函數(shù)名稱的話,如何判斷是函數(shù)聲明還是函數(shù)表達(dá)式呢?ECMAScript是通過(guò)上下文來(lái)區(qū)分的,如果function foo(){}是作為賦值表達(dá)式的一部分的話,那它就是一個(gè)函數(shù)表達(dá)式,如果function foo(){}被包含在一個(gè)函數(shù)體內(nèi),或者位于程序的最頂部的話,那它就是一個(gè)函數(shù)聲明。

function foo(){} // 聲明,因?yàn)樗浅绦虻囊徊糠?
var bar = function foo(){}; // 表達(dá)式,因?yàn)樗琴x值表達(dá)式的一部分

new function bar(){}; // 表達(dá)式,因?yàn)樗莕ew表達(dá)式

(function(){
 function bar(){} // 聲明,因?yàn)樗呛瘮?shù)體的一部分
})();

表達(dá)式和聲明存在著十分微妙的差別,首先,函數(shù)聲明會(huì)在任何表達(dá)式被解析和求值之前先被解析和求值,即使你的聲明在代碼的最后一行,它也會(huì)在同作用域內(nèi)第一個(gè)表達(dá)式之前被解析/求值,參考如下例子,函數(shù)fn是在alert之后聲明的,但是在alert執(zhí)行的時(shí)候,fn已經(jīng)有定義了:

alert(fn());

function fn() {
 return 'Hello world!';
}

另外,還有一點(diǎn)需要提醒一下,函數(shù)聲明在條件語(yǔ)句內(nèi)雖然可以用,但是沒(méi)有被標(biāo)準(zhǔn)化,也就是說(shuō)不同的環(huán)境可能有不同的執(zhí)行結(jié)果,所以這樣情況下,最好使用函數(shù)表達(dá)式: 因?yàn)樵跅l件語(yǔ)句中沒(méi)有塊級(jí)作用域這個(gè)概念

// 千萬(wàn)別這樣做!
// 因?yàn)橛械臑g覽器會(huì)返回first的這個(gè)function,而有的瀏覽器返回的卻是第二個(gè)

if (true) {
 function foo() {
 return 'first';
 }
}
else {
 function foo() {
 return 'second';
 }
}
foo();

// 相反,這樣情況,我們要用函數(shù)表達(dá)式
var foo;
if (true) {
 foo = function() {
 return 'first';
 };
}
else {
 foo = function() {
 return 'second';
 };
}
foo();

函數(shù)聲明的實(shí)際規(guī)則如下:

函數(shù)聲明只能出現(xiàn)在程序或函數(shù)體內(nèi)。從句法上講,它們 不能出現(xiàn)在Block(塊)({ … })中,例如不能出現(xiàn)在 if、while 或 for 語(yǔ)句中。因?yàn)?Block(塊) 中只能包含Statement語(yǔ)句, 而不能包含函數(shù)聲明這樣的源元素。另一方面,仔細(xì)看一看規(guī)則也會(huì)發(fā)現(xiàn),唯一可能讓表達(dá)式出現(xiàn)在Block(塊)中情形,就是讓它作為表達(dá)式語(yǔ)句的一部分。但是,規(guī)范明確規(guī)定了表達(dá)式語(yǔ)句不能以關(guān)鍵字function開(kāi)頭。而這實(shí)際上就是說(shuō),函數(shù)表達(dá)式同樣也不能出現(xiàn)在Statement語(yǔ)句或Block(塊)中(因?yàn)锽lock(塊)就是由Statement語(yǔ)句構(gòu)成的)。

2、命名函數(shù)表達(dá)式

提到命名函數(shù)表達(dá)式,理所當(dāng)然,就是它得有名字,前面的例子var bar = function foo(){};就是一個(gè)有效的命名函數(shù)表達(dá)式,但有一點(diǎn)需要記?。哼@個(gè)名字只在新定義的函數(shù)作用域內(nèi)有效,因?yàn)橐?guī)范規(guī)定了標(biāo)示符不能在外圍的作用域內(nèi)有效:

var f = function foo(){
 return typeof foo; // function --->foo是在內(nèi)部作用域內(nèi)有效
};
// foo在外部用于是不可見(jiàn)的
typeof foo; // "undefined"
f(); // "function"

既然,這么要求,那命名函數(shù)表達(dá)式到底有啥用???為啥要取名?

正如我們開(kāi)頭所說(shuō):給它一個(gè)名字就是可以讓調(diào)試過(guò)程更方便,因?yàn)樵谡{(diào)試的時(shí)候,如果在調(diào)用棧中的每個(gè)項(xiàng)都有自己的名字來(lái)描述,那么調(diào)試過(guò)程就太爽了,感受不一樣嘛。

tips:這里提出一個(gè)小問(wèn)題:在ES3中,命名函數(shù)表達(dá)式的作用域?qū)ο笠怖^承了 Object.prototype 的屬性。這意味著僅僅是給函數(shù)表達(dá)式命名也會(huì)將 Object.prototype 中的所有屬性引入到作用域中。結(jié)果可能會(huì)出人意料。

var constructor = function(){return null;}
var f = function f(){
 return construcor();
}
f(); //{in ES3 環(huán)境}

該程序看起來(lái)會(huì)產(chǎn)生 null, 但其實(shí)會(huì)產(chǎn)生一個(gè)新的對(duì)象。因?yàn)槊瘮?shù)表達(dá)式在其作用域內(nèi)繼承了 Object.prototype.constructor(即 Object 的構(gòu)造函數(shù))。就像 with 語(yǔ)句一樣,這個(gè)作用域會(huì)因 Object.prototype 的動(dòng)態(tài)改變而受到影響。幸運(yùn)的是,ES5 修正了這個(gè)錯(cuò)誤。

這種行為的一個(gè)合理的解決辦法是創(chuàng)建一個(gè)與函數(shù)表達(dá)式同名的局部變量并賦值為 null。即使在沒(méi)有錯(cuò)誤地提升函數(shù)表達(dá)式聲明的環(huán)境中,使用 var 重聲明變量能確保仍然會(huì)綁定變量 g。設(shè)置變量 g 為 null 能確保重復(fù)的函數(shù)可以被垃圾回收。

var f = function g(){
 return 17;
}
var g =null;

3、調(diào)試器(調(diào)用棧)中的命名函數(shù)表達(dá)式

剛才說(shuō)了,命名函數(shù)表達(dá)式的真正用處是調(diào)試,那到底怎么用呢?如果一個(gè)函數(shù)有名字,那調(diào)試器在調(diào)試的時(shí)候會(huì)將它的名字顯示在調(diào)用的棧上。有些調(diào)試器(Firebug)有時(shí)候還會(huì)為你們函數(shù)取名并顯示,讓他們和那些應(yīng)用該函數(shù)的便利具有相同的角色,可是通常情況下,這些調(diào)試器只安裝簡(jiǎn)單的規(guī)則來(lái)取名,所以說(shuō)沒(méi)有太大價(jià)值,我們來(lái)看一個(gè)例子:不用命名函數(shù)表達(dá)式

function foo(){
 return bar();
}
function bar(){
 return baz();
}
function baz(){
 debugger;
}
foo();

// 這里我們使用了3個(gè)帶名字的函數(shù)聲明
// 所以當(dāng)調(diào)試器走到debugger語(yǔ)句的時(shí)候,F(xiàn)irebug的調(diào)用棧上看起來(lái)非常清晰明了 
// 因?yàn)楹苊靼椎仫@示了名稱
baz
bar
foo
expr_test.html()

通過(guò)查看調(diào)用棧的信息,我們可以很明了地知道foo調(diào)用了bar, bar又調(diào)用了baz(而foo本身有在expr_test.html文檔的全局作用域內(nèi)被調(diào)用),不過(guò),還有一個(gè)比較爽地方,就是剛才說(shuō)的Firebug為匿名表達(dá)式取名的功能:

function foo(){
 return bar();
}
var bar = function(){
 return baz();
}
function baz(){
 debugger;
}
foo();

// Call stack
baz
bar() //看到了么? 
foo
expr_test.html()

然后,當(dāng)函數(shù)表達(dá)式稍微復(fù)雜一些的時(shí)候,調(diào)試器就不那么聰明了,我們只能在調(diào)用棧中看到問(wèn)號(hào):

function foo(){
 return bar();
}
var bar = (function(){
 if (window.addEventListener) {
 return function(){
  return baz();
 };
 }
 else if (window.attachEvent) {
 return function() {
  return baz();
 };
 }
})();
function baz(){
 debugger;
}
foo();

// Call stack
baz
(?)() // 這里可是問(wèn)號(hào)哦,顯示為匿名函數(shù)(anonymous function)
foo
expr_test.html()

另外,當(dāng)把函數(shù)賦值給多個(gè)變量的時(shí)候,也會(huì)出現(xiàn)令人郁悶的問(wèn)題:

function foo(){
 return baz();
}
var bar = function(){
 debugger;
};
var baz = bar;
bar = function() { 
 alert('spoofed');
};
foo();

// Call stack:
bar()
foo
expr_test.html()

這時(shí)候,調(diào)用棧顯示的是foo調(diào)用了bar,但實(shí)際上并非如此,之所以有這種問(wèn)題,是因?yàn)閎az和另外一個(gè)包含alert(‘spoofed')的函數(shù)做了引用交換所導(dǎo)致的。

歸根結(jié)底,只有給函數(shù)表達(dá)式取個(gè)名字,才是最委托的辦法,也就是使用命名函數(shù)表達(dá)式。我們來(lái)使用帶名字的表達(dá)式來(lái)重寫上面的例子(注意立即調(diào)用的表達(dá)式塊里返回的2個(gè)函數(shù)的名字都是bar):

function foo(){
 return bar();
}
var bar = (function(){
 if (window.addEventListener) {
 return function bar(){
  return baz();
 };
 }
 else if (window.attachEvent) {
 return function bar() {
  return baz();
 };
 }
})();
function baz(){
 debugger;
}
foo();

// 又再次看到了清晰的調(diào)用棧信息了耶!
baz
bar
foo
expr_test.html()

好的,整個(gè)文章結(jié)束,大家對(duì)javascript的認(rèn)識(shí)又近了一步,希望大家越來(lái)越喜歡小編為大家整理的文章,繼續(xù)關(guān)注跟我學(xué)習(xí)javascript的一系列文章。

相關(guān)文章

  • JavaScript中16進(jìn)制顏色與rgb顏色互相轉(zhuǎn)換的示例代碼

    JavaScript中16進(jìn)制顏色與rgb顏色互相轉(zhuǎn)換的示例代碼

    這篇文章主要介紹了JavaScript中16進(jìn)制顏色與rgb顏色互相轉(zhuǎn)換的示例代碼,通過(guò)示例代碼介紹了JS 顏色16進(jìn)制、rgba相互轉(zhuǎn)換問(wèn)題,感興趣的朋友一起看看吧
    2024-01-01
  • Javascript中replace方法與正則表達(dá)式的結(jié)合使用教程

    Javascript中replace方法與正則表達(dá)式的結(jié)合使用教程

    replace方法是javascript涉及到正則表達(dá)式中較為復(fù)雜的一個(gè)方法,嚴(yán)格上說(shuō)應(yīng)該是string對(duì)象的方法,下面這篇文章主要給大家介紹了關(guān)于Javascript中replace方法與正則表達(dá)式的結(jié)合使用的相關(guān)資料,需要的朋友可以參考下
    2022-09-09
  • JavaScript實(shí)現(xiàn)函數(shù)重載的代碼示例

    JavaScript實(shí)現(xiàn)函數(shù)重載的代碼示例

    在JavaScript中并沒(méi)有直接支持函數(shù)重載的機(jī)制,但是可以通過(guò)一些技巧來(lái)模擬函數(shù)重載的效果,比如使用參數(shù)判斷,使用默認(rèn)參數(shù),對(duì)象參數(shù),這些方法都可以實(shí)現(xiàn)類似函數(shù)重載的效果,所以本文就給大家介紹一下JavaScript如何實(shí)現(xiàn)函數(shù)重載,需要的朋友可以參考下
    2023-08-08
  • JavaScript運(yùn)動(dòng)原理基礎(chǔ)知識(shí)詳解

    JavaScript運(yùn)動(dòng)原理基礎(chǔ)知識(shí)詳解

    這篇文章主要介紹了JavaScript運(yùn)動(dòng)原理基礎(chǔ)知識(shí)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • 原生js仿jq判斷當(dāng)前瀏覽器是否為ie,精確到ie6~8

    原生js仿jq判斷當(dāng)前瀏覽器是否為ie,精確到ie6~8

    這篇文章主要介紹了原生js仿jq判斷當(dāng)前瀏覽器是否為ie,精確到ie6~8,需要的朋友可以參考下
    2014-08-08
  • js實(shí)現(xiàn)類似菜單風(fēng)格的TAB選項(xiàng)卡效果代碼

    js實(shí)現(xiàn)類似菜單風(fēng)格的TAB選項(xiàng)卡效果代碼

    這篇文章主要介紹了js實(shí)現(xiàn)類似菜單風(fēng)格的TAB選項(xiàng)卡效果代碼,通過(guò)javascript鼠標(biāo)事件及頁(yè)面元素遍歷實(shí)現(xiàn)tab切換的功能,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下
    2015-08-08
  • svg動(dòng)畫之動(dòng)態(tài)描邊效果

    svg動(dòng)畫之動(dòng)態(tài)描邊效果

    本文主要介紹了svg實(shí)現(xiàn)的動(dòng)態(tài)描邊效果,文中分享了兩個(gè)實(shí)例:1.一個(gè)簡(jiǎn)單的線一點(diǎn)一點(diǎn)畫出來(lái)的效果;2.用同樣的原理畫一個(gè)“藍(lán)胖子”。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-02-02
  • js實(shí)現(xiàn)酷炫倒計(jì)時(shí)動(dòng)畫

    js實(shí)現(xiàn)酷炫倒計(jì)時(shí)動(dòng)畫

    這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)酷炫倒計(jì)時(shí)動(dòng)畫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • Webpack?ECMAScript?模塊詳解

    Webpack?ECMAScript?模塊詳解

    ECMAScript 模塊(ESM)是在 Web 中使用模塊的規(guī)范, 所有現(xiàn)代瀏覽器均支持此功能,同時(shí)也是在 Web 中編寫模塊化代碼的推薦方式,這篇文章主要介紹了Webpack?ECMAScript?模塊,需要的朋友可以參考下
    2023-12-12
  • Bootstrap導(dǎo)航條學(xué)習(xí)使用(二)

    Bootstrap導(dǎo)航條學(xué)習(xí)使用(二)

    這篇文章主要為大家詳細(xì)介紹了Bootstrap導(dǎo)航條的使用方法第二篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-02-02

最新評(píng)論