日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JavaScript 变量、函数与原型链

發布時間:2024/9/5 javascript 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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。
        @定義函數的作用:除了指明函數作用域,同時定義函數體結構——包括函數體內部的變量定義和函數定,此過程遞歸。

alert(a); //function a(){}alert(b); //function b(){}alert(c); //undefinedvar a = "a";function a() {}function b() {}var b = "b";var c = "c";var c = function() {}alert(a); //aalert(b); //balert(c); //function(){} ①雖然第一個 alert(a) 在最前面,但是你會發現它輸出的值竟然是 function a() {},這說明,函數定義確實在整個程序執行之前就已經完成了。 ②再來看 b,函數 b 定義在變量 b 之前,但是第一個 alert(b) 輸出的仍然是 function b() {},這說明,變量定義確實不對變量做什么,僅僅是聲明它的作用域而已,它不會覆蓋函數定義。 ③最后看 c,第一個 alert(c) 輸出的是 undefined,這說明 var c = function() {} 不是對函數 c 定義,僅僅是定義一個變量 c 和一個匿名函數。 ④再來看第二個 alert(a),你會發現輸出的竟然是 a,這說明賦值語句確實是在執行過程中完成的,因此,它覆蓋了函數 a 的定義。 ⑤第二個 alert(b) 當然也一樣,輸出的是 b,這說明不管賦值語句寫在函數定義之前還是函數定義之后,對一個跟函數同名的變量賦值總會覆蓋函數定義。 ⑥第二個 alert(c) 輸出的是 function() {},這說明,賦值語句是順序執行的,后面的賦值覆蓋了前面的賦值,不管賦的值是函數還是其它對象。 練習

    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的變量能存儲直接量 也能存儲引用量。
        在大字符串連接 和 循環里賦值等地方,需留意此變量特性對執行效率的影響。

var x=""; var big = "這里是一大坨字符串..."; for (i=0; i<100; i++){a += big; } x = a; //因為是字符串操作,使用直接量,每次循環都要操作大字符串,非常笨重,效率低下。如果改用引用量操作,即通過數組,效率甚至會提高十幾倍: var s = "這里又是一大坨字符串..."; var a = []; for (i=0; i<100; i++){a[i] = s; } s = a.join(""); 優化 循環賦值 執行效率

?     4-原型的定義和賦值
      原型:如果構造器有個原型對象A,由構造器創建的對象實例(Object Instance)都復制于原型對象A。
       ?、倜總€對象都有一個原型鏈,由自身向上包含一個或多個對象,本身為起始對象。
        ②在JavaScript中,一個對象 或 一個對象實例沒有原型,不存在“持有某個原型”的說法,只存在“構造自某個原型”的說法。
                構造器才有原型,<構造器>.prototype屬性指向原型。

function fn() {var name = "大蝦";var age = 23;function code() {alert("切克鬧!");}; } var obj = new fn();

        上述代碼中:
         ?、賝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,函數原型的構造器 默認為函數本身。

      對象實例 復制構造器的原型對象時,采用的是讀遍歷機制復制的。
        讀遍歷機制:指僅當寫某個實例的成員時,將成員信息復制到實例映像中。
              即構造的新對象里面的屬性 指向原型中的屬性。讀取對象實例的屬性時,獲取的是原型對象的屬性值。

Object.prototype.value = "abc";var obj1 = new Object();var obj2 = new Object();obj2.value = 10;alert(obj1.value);//輸出abc,讀取的是原型Object中的valuealert(obj2.value);//輸出10,讀取的是obj2成員列表中的valuedelete obj2.value;//刪除obj2中的value,即在obj2的成員列表中將value刪除掉alert(obj2.value);//輸出abc,讀取的是原型Object中的value

?              

      上述說明了讀遍歷機制 如何管理實例對象成員列表 和 原型中的對象成員。
       ?、僦挥械谝淮螌傩赃M行寫操作時,才會在對象的成員列表中 添加該屬性的記錄。
       ?、诋攐bj1和obj2通過new構造出來,只是一個指向原型的引用,這樣的讀遍歷 避免了創建對象實例可能的大量內存分配。
       ?、踥bj2.value屬性被賦值10時,obj2的成員表中添加了一個value成員并賦值10。
          此成員表記錄了對象發送了修改的成員名、值與類型。遵循2個原則:
          a、保證在讀取是首先訪問。
          b、對象中午指定屬性時,遍歷對象的整條原型鏈,直到原型為空或找到該屬性。
       ?、躣elete obj2.value刪除的是成員表的屬性。

      原型的構造器
        函數的原型 是內置的Object()構造器的一個實例。但該對象實例創建后,constructor屬性總會先被賦值為當前函數。
        究其根源在于構造器(構造函數)的原型(prototype)的constructor屬性指向構造器本身。

function MyObject() { }alert(MyObject.prototype.constructor == MyObject); //顯示true,表明原型的構造器總是指向函數自身的delete MyObject.prototype.constructor; //刪除該成員(指向自身的原型構造器) alert(MyObject.prototype.constructor == Object); alert(MyObject.prototype.constructor == new Object().constructor); //刪除操作使該成員指向了父代類原型中的值 //均顯示為true

?        上例中,myObject.protptype與new Object()沒有實質區別,只是在創建時將myObject的constructor值賦值為自身。
        函數與構造器并沒有明顯的界限:
          當指定一個函數的prototype時,該函數就會成為構造器。
          此時用new創建實例時,引擎會構造一個新對象,把這個新對象的原型鏈 連接向該函數prototype屬性就可以了。

?      原型繼承中的“原型復制”
        通過設置 不同構造器創建出來的實例的constructor屬性,能指向同個構造器。

function MyObject() { } function MyObjectEx() { } MyObjectEx.prototype = new MyObject(); var obj1 = new MyObject(); var obj2 = new MyObjectEx(); alert(obj2.constructor == MyObject); //true alert(MyObjectEx.prototype.constructor == MyObject); //true

        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 变量、函数与原型链的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。