javascript
JavaScript 变量、函数与原型链
定義 || 賦值
1-函數的定義
函數定義的兩種方式:
“定義式”函數:function fn(){ alert("喲,喲!"); }
“賦值式”函數:var fn = function(){ alert("切可鬧!"); }
@頁面加載時,瀏覽器會對JavaScript代碼進行掃描,并將 定義式函數進行預處理(類似C等的編譯)?!竞瘮德暶魈嵘?br /> 處理完再由上至下執行,遇到賦值式函數 則只是將函數賦值給一個變量,不進行預處理,待調用時才進行處理。
@在定義前面調用函數時,定義式函數正常執行,賦值式函數會報錯 (提示:oFn is not a function)。
2-變量與函數的定義
變量:①var a; 定義變量a。
?、趘ar a = 123; 定義變量a,再給變量a賦值。
函數:①function fn(...){...} 聲明函數fn。
?、趘ar oFn = function(...){...} 先定義變量oFn和一個匿名函數,再將匿名函數賦值給變量oFn。
@定義變量和定義函數都會先預處理,變量賦值則是在執行中完成。
@定義變量的作用:只是指明變量作用域。
有定義沒賦值的變量 和 使用沒定義的變量 值都為undefined。
@定義函數的作用:除了指明函數作用域,同時定義函數體結構——包括函數體內部的變量定義和函數定,此過程遞歸。
3-變量賦值
對于弱類型的JavaScript,聲明變量不需要聲明其類型。
隨之的問題,在使用 直接量和引用量 卻混亂一片:
?、賤ar x = "111"; var y = x; x = "222"; alert(y);
在JavaScript中,此時y值為111,即字符串的賦值是直接量操作,直接把數據賦值給y的存儲空間。
在java等語言中,y的值為222,即x在存儲器中將地址(指針)賦給變量y。
?、趘ar x = ["111"]; var y = x; x[0] = "222"; alert(y[0]);
在JavaScript中,此時卻與①不同,y[0]值為222,引用量操作,即x把在存儲器中的地址(指針)賦給了y。
?、踲ar x = ["111"]; var y = x; x = ["222","333"]; alert(y[0]);
在Javascript中,此時y的值又是111,即此賦值又是直接量操作。
JavaScript解析器 對不同類型的差異:
var x = "xxxx"; var y = ["11","22"];
?、僭谧址?#xff0c;解析器直接把字符串賦給變量x(直接量)。
?、谠跀到M中,解析器把數組的指針賦給變量y(引用量)。
上述問題②中,x[o] = "222"由于沒有給x新定義值,沒有新開辟存儲空間,只修改了它存儲空間里的數據,故還是引用量。
上述問題③中,創建var x = ["111"]時,解析器在內存中為數組創建存儲空間,x則獲得該空間的地址(指針),
再執行x = ["2","3"]給數組新定義值時,解析器會開辟新存儲空間放這個數組,x則為新存儲空間的指針。
由上述可知,JavaScript的變量能存儲直接量 也能存儲引用量。
在大字符串連接 和 循環里賦值等地方,需留意此變量特性對執行效率的影響。
? 4-原型的定義和賦值
原型:如果構造器有個原型對象A,由構造器創建的對象實例(Object Instance)都復制于原型對象A。
?、倜總€對象都有一個原型鏈,由自身向上包含一個或多個對象,本身為起始對象。
②在JavaScript中,一個對象 或 一個對象實例沒有原型,不存在“持有某個原型”的說法,只存在“構造自某個原型”的說法。
構造器才有原型,<構造器>.prototype屬性指向原型。
上述代碼中:
?、賝bj為對象實例,fn為一個構造器。
②obj.prototype; //undefined,對象實例沒有原型。
fn.prototype; //[object Object],原型是一個對象。
?、踥bj.constructor; //輸出fn()的函數代碼。
fn.construtor; //function Function(){[native code]},native code表示JavaScript引擎的內置函數。
obj.construtor == fn; //true,obj構造自fn。
?、躥n.prototype.construtor == fn; //true,函數原型的構造器 默認為函數本身。
對象實例 復制構造器的原型對象時,采用的是讀遍歷機制復制的。
讀遍歷機制:指僅當寫某個實例的成員時,將成員信息復制到實例映像中。
即構造的新對象里面的屬性 指向原型中的屬性。讀取對象實例的屬性時,獲取的是原型對象的屬性值。
?
上述說明了讀遍歷機制 如何管理實例對象成員列表 和 原型中的對象成員。
?、僦挥械谝淮螌傩赃M行寫操作時,才會在對象的成員列表中 添加該屬性的記錄。
?、诋攐bj1和obj2通過new構造出來,只是一個指向原型的引用,這樣的讀遍歷 避免了創建對象實例可能的大量內存分配。
?、踥bj2.value屬性被賦值10時,obj2的成員表中添加了一個value成員并賦值10。
此成員表記錄了對象發送了修改的成員名、值與類型。遵循2個原則:
a、保證在讀取是首先訪問。
b、對象中午指定屬性時,遍歷對象的整條原型鏈,直到原型為空或找到該屬性。
?、躣elete obj2.value刪除的是成員表的屬性。
原型的構造器
函數的原型 是內置的Object()構造器的一個實例。但該對象實例創建后,constructor屬性總會先被賦值為當前函數。
究其根源在于構造器(構造函數)的原型(prototype)的constructor屬性指向構造器本身。
? 上例中,myObject.protptype與new Object()沒有實質區別,只是在創建時將myObject的constructor值賦值為自身。
函數與構造器并沒有明顯的界限:
當指定一個函數的prototype時,該函數就會成為構造器。
此時用new創建實例時,引擎會構造一個新對象,把這個新對象的原型鏈 連接向該函數prototype屬性就可以了。
? 原型繼承中的“原型復制”
通過設置 不同構造器創建出來的實例的constructor屬性,能指向同個構造器。
obj1和obj2是由不同的兩個構造器(MyObject和MyObjectEx)產生的實例。然而,兩個alert都會輸出true,即由兩個不相同的構造器產生的實例,它們的constructor屬性卻指向了相同的構造器。這體現了原型繼承中的“原型復制”。MyObjectEx的原型是由MyObject構造出來的對象實例,即obj1和obj2都是從MyObject原型中復制出來的對象,因此它們的constructor指向的都是MyObject!
?
轉載于:https://www.cnblogs.com/slowsoul/archive/2013/05/30/3107198.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的JavaScript 变量、函数与原型链的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 点聚WebOffice 控件 使用Loa
- 下一篇: JavaScript 解决浮点值运算Bu