你應該知道的幾個js知識

來源:互聯網
上載者:User

標籤:c   style   class   blog   code   java   

1.在javascript的塊級範圍是以函數來決定的.

     if(true){         var scopeName = "felayman";     }    print(scopeName);
上述雖然scopeName是在{}內聲明的,但是它不屬於塊級範圍,在{}範圍內依然能進行訪問.因此,如果想在javascript中聲明一個塊級範圍,需要藉助於函數來實現,如

 <span style="font-size:18px;"> function scope(){        if(true){            var scopeName = "felayman";        }    }</span>
這樣,scopeName才屬於一個函數級(塊級)範圍,在函數外是無法訪問scopeName的.

2.javascript中的變數尋找鏈,如

 <span style="font-size:18px;">   var scope = "golbalScope";    var fun = function(){       alert(scopr);        var scope = "funcScope";    };    fun();</span>
其結果為undefined,上述的代碼可能跟我們所想的有所不同,沒有輸出golbalScope,也沒有輸出funcScope,而是輸出了undefined?這是聲明原因呢?這個是javascript的一個重要特性---範圍搜尋順序,當我們去訪問某個變數的時候,它會優先搜尋scope所在環境,因此搜尋到了var scope = "funcScope";,因此會

拋棄掉上一級環境的var scope = "golbalScope";也就是var scope = "golbalScope";會被變數scope所在的環境給屏蔽掉,然後當程式執行到alert(scope);的時候,但是

scope在當前環境中並沒有進行初始化,因而輸出了undefined.

3.javascript的函數範圍的嵌套

<span style="font-size:18px;"> var fun = function(){    var scope = "scope_one";    (function(){        alert(scope);        var scope = "scope_two";        (function(){            alert(scope);        })();    })();};fun();</span>

這個例子的結果為,undefined和scope_two,正如上面一個例子一樣,我們可以理解其結果行為,但是我們必須去注意,函數範圍的嵌套關係是在定義的時候決定的,而不是調用的時候決定的,也就是說,javascript的範圍是靜態範圍,也叫詞法範圍,這個例子主要是想說明閉包,在javscript中,一般情況下閉包就是匿名函數,而關於閉包的定義,有這麼一種說法:由函數及其封閉的自由變數組成的集合體.,因此在一般情況下,在javascript我們視函數即為閉包,我們看一個例子

<span style="font-size:18px;">function print(s){document.write(s+"<br/>")};  var getResult = function(){    var count = 0;    var get = function(){        count++;        return count;    };    return get;};var counter = getResult();print(counter());print(counter());print(counter());</span>
結果為1,2,3.如果熟悉其他語言,或許會恨困惑這個結果,因為函數,俗稱方法,在其他語言中就是一個儲存臨時變數和結果的一個容器,當函數執行完畢後,會釋放該函數內的所有的局部變數和臨時結果,因此當我們每次調用同一個函數的時候,其結果是不變的,但是在jabascript,卻因為閉包改變了這個規則.這個也是閉包的特性---當一個函數返回它內部定義的一個函數的時候,就產生了一個閉包,閉包不但包括被返回的函數,還包括這個函數的定義環境,上面的例子,當函數getResult()的內建函式get被一個外部變數counter引用的時候,counter和getResult()的局部變數就形成一個閉包.因此上述的counter()其實就是get(),列印counter()的值,就是列印get()的值,但是於此同時get()函數屬於getResult()函數內部的一個閉包(或者可以理解一個布局變數,或者理解get()在getResult()函數的範圍內),在該閉包內依然引用著它的上一級範圍,即getResult()函數範圍,具體的說,在get()函數內部使用了getResult()函數內的變數,因此,雖然我們在getResult()函數外部調用了一個看似與getResult()函數關係不大的counter()函數,但是卻是在getResult()函數內部環境去執行的counter()函數.也就是說print(counter());
print(counter());print(counter());)這段代碼看似是在getResult()外部執行,其實本質上是在getResult()函數內部執行的,因此上述代碼完全等效於下述代碼:

<span style="font-size:18px;">/** * Created by felayman on 2014/5/27. */  function print(s){document.write(s+"<br/>")};  var getResult = function(){    var count = 0;    var get = function(){        count++;        return count;    };    print(get());    print(get());    print(get());};getResult()</span>;
但是如果我們在使用的時候這樣使用的話,就沒有閉包的優勢了----與外界失去了聯絡,也就是與其他語言中的函數(方法)一樣的,而javascript中的函數,也正是由於閉包的特性,才被稱為最實用於函數式編程的語言.
4.this所指向的內容

 function print(s){document.write(s+"<br/>")}    var func1 = {        name:"func1scope",        func:function(){            print(this.name);        }    };    var func2 = {        name:"func2scope"    };    func1.func();  //輸出func1    func2.func = func1.func;    func2.func();  //輸出func2    var name = "windowscopr";    window.func = func1.func;    func();

上述代碼會輸出:func1scope   func2scope    windowscopr,因此,可以看出this的指向是隨著其環境而發生變化,但是我們只需要記著一句話即可---this始終指向其執行期間的環境對象,而非定義時的環境對象.

5.call和apply

如果說在javascript中最讓人困惑和難以理解的,

其中call和apply的功能是以不同的對象作為上下文來調用某個對象的函數,或者--就是允許在一個對象中去調用另一個對象中的同名函數(沒有會被複製)並執行(摘自--NodeJS開發指南).如下面的例子:

<span style="font-size:18px;">var oneUser = {    name:"oneUser",    getName:function(){        alert(this.name);    }};var otherUser = {    name:"otherUser",};oneUser.getName.call(otherUser);</span>
可以這樣理解,我們以每一個對象內部都有一個call對象(函數就是對象),該對象沒有具體指向,但是允許指向任何一個對象內部的另一個對象.而applay與call的用法沒有上面區別,只是接受的參數不同而已.
6.原型

如果要給原型一個定義,百度百科上說的很詳細,但是很抽象,很難理解,而在NodeJs開發指南中,作者用了一個很好的例子----原型就好像是一件藝術品的原件,我們通過一台100%精確的機器把這個原件複製出很多件,如果我們瞭解類似java的物件導向語言的話,就會知道,在java中所有的對象都來自於類,而C++中所有的對象來自於構造器,但是javascript是一種基於物件導向語言,它既有類似C++的構造器,也有類似類的原型.其實我更傾向於一篇博文中的理解,在javascript中

,原型就是java中的一個類的一個對象,該Object Storage Service該類的所有靜態屬性或方法.我更建議使用這種方法來理解原型.因為的確是這樣的,javascript中使用原型的目的就是讓某一類型的所有對象共用一些屬性和函數,提供代碼的複用性,同時也隱藏一些屬性和函數的細節,即提高其內聚性和封裝性,這也是javascript基於物件導向的特性.

<span style="font-size:18px;">function Person(name,age,job){    this.name = name;    this.age = age;    this.job = job;    this.getInfo = function(){        return "name ="+this.name+",age = "+ this.age+",job = " +this.job;    }}</span>

上述代碼沒有使用,原型,因此我們在使用new關鍵字來建立對象的時候,可以根據不同的name,age,job來構件許許多多的Person的對象,這些對象的屬性都不相同,但是作為常識,我們都知道Person都有一個共同的行為--說話(不去鑽牛角尖),當然我們可以改寫上面的代碼來滿足我們的需求:

<span style="font-size:18px;">function Person(name,age,job){    this.name = name;    this.age = age;    this.job = job;    this.getInfo = function(){        return "name ="+this.name+",age = "+ this.age+",job = " +this.job;    }    this.say = function(){        alert("人都會說話");    }}</span>

這樣的代碼是允許的,但是不是被建議的,因為我們在建立一個Person對象的時候,就會在記憶體中產生say()函數的內容空間,或許在少量的這樣的行為的時候我們允許這麼做,但是我們再思考一下,如果一個函數中有大量的行為或者屬性都像say()函數一樣是每一個Person對象所共同擁有的,必然Person會說話,會跑,會思考,會苦,會笑.........如果有了大量類似的屬性或行為的話,我們還是寫在函數內部的話,就不好了,因為我們在建立基量很大的對象數量的時候,我們就額外增加了非必須且可避免的記憶體開銷了,因為每個對象在記憶體中都會開闢其所擁有的方法空間,這是不建議的,因此,我們使用了原型的話,這個問題就可以避免了,我們只需要在記憶體的其他地方建立一個原型對象,改對象儲存著Person所有的共同屬性或者方法,只要在每個Person執行個體對象中儲存一個指向改記憶體空間的引用或控制代碼即可.這樣當我們即使建立再多Person執行個體對象,也沒有多少記憶體開銷,這個理解就是javascript原型的特性之一.因此上述代碼改寫成下面就好了:

<span style="font-size:18px;">function Person(name,age,job){    this.name = name;    this.age = age;    this.job = job;}Person.prototype.getInfo = function(){    return "name = "+this.name+",age = "+this.age+",job ="+this.job;};Person.prototype.say  =function(){    console.log("人都會說話");};</span>






聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.