JS中有關對象的繼承以及執行個體化、淺拷貝深拷貝的奧秘

來源:互聯網
上載者:User

標籤:凍結   建立對象   delete   enum   his   使用方法   返回   for   efi   

一、屬性的歸屬問題

JS對象中定義的屬性和方法如果不是掛在原型鏈上的方法和屬性(直接通過如類似x的方式進行定義)都只是在該對象上,對原型鏈上的沒有影響。對於所有執行個體共用的方法可直接定義在原型鏈上這樣執行個體化的的時候就不用對每個執行個體定義該屬性方法,所有的執行個體均具有該方的引用見最後的輸出。

function Myclass(){this.x=" x in Myclass";this.get=function(){}//每次執行個體化對象,每個對象的該方法都是獨立的,是不相同的}Myclass.prototype.y="y in Myclass";Myclass.prototype.set=function(){};//所有執行個體共用該方法,對於該方法具有同一個執行個體var obj=new Myclass();console.log(obj.y);//y in Myclassobj.y="override y";//尋找屬性時現在當前的對象上找,沒找到才到原型鏈上尋找console.log(obj.y);//override ydelete obj.y //trueconsole.log(obj.y);//y in Myclassvar obj2=new Myclass();console.log(obj2.y);//y in Myclassobj.z=‘zzz‘; console.log(obj.z);//zzzconsole.log(obj2.z);//undefinedconsole.log(obj.prototype);//undefinedconsole.log(obj.get===obj2.get)//false;console.log(obj.set===obj2.set)//true,所有的執行個體具有相同的引用

二、JS中有關原型的__proto__和prototype的差別:

所有的執行個體對象都具有__proto__來表示其原型,prototype是方法具有的屬性,非對象的方法的該屬性為null,這兩者都用於表示對象的原型鏈,由於很多場合下前者是私人屬性一般不直接使用故可以用Object.getPrototypeOf(obj)的方式擷取到原型對象,Object.create()中傳入的即為建立對象的原型。

function Myclass(){this.x=" x in Myclass";this.get=function(){}//每次執行個體化對象,每個對象的該方法都是獨立的,是不相同的}Myclass.prototype.y="y in Myclass";Myclass.prototype.set=function(){};//所有執行個體共用該方法,對於該方法具有同一個執行個體var obj=Object.create(new Myclass());//obj.__proto__.y=10;console.log(obj.__proto__);console.log(Myclass.prototype);var obj2=new Myclass();console.log(Myclass.prototype===obj.__proto__.__proto__);//tureconsole.log(obj.x);console.log(Object.getPrototypeOf(obj2)===Myclass.prototype);//true

三、對象的執行個體化和繼承

   利用new進行執行個體化對象,利用原型(prototype)實現繼承,在繼承時只會繼承原型鏈上的屬性和方法,不會繼承掛在對象自身上的屬性和方法,執行個體化時對象具有所有的屬性和方法。

function Myclass(){this.x=" x in Myclass";//每次執行個體化對象,每個對象的該方法都是獨立的,沒有被繼承this.get=function(){}}Myclass.prototype.y="y in Myclass";Myclass.prototype.set=function(){};//所有執行個體共用該方法,對於該方法具有同一個引用,定義在原型鏈上的屬性和方法都會被繼承var obj=Object.create(Myclass.prototype);//create的第一個參數必須是原型,第二個參數用於定義屬性和defineProperties/defineProperty使用方法相同console.log(obj.x);//undefinedconsole.log(obj.y);// y in Myclass

    因而可以通過混合模式定義對象實現屬性或者方法的部分繼承,不想被繼承的利用建構函式的方式this.property方式定義,想要被繼承的直接定義在原型鏈上(如上面的只繼承了y屬性和set方法,其他的x等就沒有被繼承)。不過如果直接執行個體化會具有所有的屬性和方法。通過create的方式則只具有繼承的屬性和方法。

//繼承的時利用執行個體化的對象作為原型不會影響原對象執行個體化出來的對象

function Myclass(){this.x=" x in Myclass";this.get=function(){}//每次執行個體化對象,每個對象的該方法都是獨立的,是不相同的}Myclass.prototype.y="y in Myclass";Myclass.prototype.set=function(){};//所有執行個體共用該方法,對於該方法具有同一個執行個體function obj(){};obj.prototype=new Myclass();var obj1=new obj();//利用create出來的對象是執行個體是不能執行個體化的obj1.x=12;var obj2=new Myclass();console.log(obj2.x);//  x in Myclassconsole.log(obj1.x); //12

1、JS中可以直接使用delete對對象的屬性進行刪除,但是不能刪除原型鏈上的屬性,和普通變數,同時當對象中的屬性配置false時不可以刪除該屬性

  1,對象屬性刪除(delete無法刪除原型鏈上的屬性)

function fun(){this.name = ‘mm‘; }var obj = new fun();console.log(obj.name);//mmdelete obj.name;console.log(obj.name); //undefined

2,變數刪除(在strict 模式下不能利用delete刪除變數)

var name = ‘lily‘;delete name;console.log(name); //lily

 

直接用delelte刪除不了變數

3,刪除不了原型鏈中的變數

fun.prototype.age = 18;delete obj.age;console.log(obj.age) //18

四、對象的淺拷貝深拷貝

深拷貝、淺拷貝:淺拷貝:不會繼續對對象裡面的對象進行解析賦值function deepCopy(p, c) {    var c = c || {};    for (var i in p) {     c[i] = p[i];         }    return c;  }深拷貝:function deepCopy(p, c) {    var c = c || {};    for (var i in p) {      if (typeof p[i] === ‘object‘) {        c[i] = (p[i].constructor === Array) ? [] : {};        deepCopy(p[i], c[i]);      } else {         c[i] = p[i];      }    }    return c;  } 
比較兩個對象那個是否相等如果直接用==、===比較的是對象的引用,當對象的引用是相同的時則相等。上訴進行拷貝的方式對象那個都是不相等的,只有賦值的才是相等的。所以判斷對象是否相等要注意是只要屬性名稱、個數、值直接相等就是相等還是通過類型引用判斷的。

五、對象中常用的方法

1、通過Object.preventExtention(a)可以對a對象禁止擴充

2、利用Object.seal()對對象進行密封是的對象不可配置和重新賦值

3、利用Object.freeze()對對象進行凍結使對象只能夠讀取

4、訪問對象中的屬性如果沒有定義會返回undefined但是訪問沒有定義的變數時會提示  Uncaught ReferenceError

5、對象中判斷某個屬性是否存在的方法:

(1)‘a’ in myobject 判斷a屬性是否在myobject中(會對原型鏈進行尋找)

(2)myobject.hasOwnProperty(‘a’)這個只會當前對象上尋找自生的屬性是否存在但是不會在原型鏈上尋找。

以上兩種方式都可以對不可枚舉的屬性進行尋找

不可枚舉的屬性是不能被遍曆得到的

6、propertyIsEnumerale()用於判斷屬性是不是可枚舉的

7、Object.keys()用於擷取所有自身的可枚舉屬性的屬性名稱(不包括原型鏈上繼承的)

8、for in 迴圈可遍曆對象那個所有的自身以及整合的可枚舉的屬性

9、Object.hasOwnProperty()判斷某個屬性是不是對象自身的屬性(其中包括不可枚舉的),利用for in結合即可擷取所有自身可枚舉屬性

10、Object.getOwnPropertyNames()擷取對象自身的所有的屬性名稱

JS中的對象(如數組、方法、object)直接賦值給其他變數傳遞的是對象的引用,賦值後會相互影響。如: var aa={a:1,b:2};

var bb=aa;//直接將aa對象賦值,其實是將aa對象的引用賦給bb

bb.a=2;

console.log(aa);//Object {a: 2, b: 2},aa的結果受到影響。

對象直接賦值會導致動一處導致多處影響,所以最好利用拷貝的方式進行賦值。

 

JS中有關對象的繼承以及執行個體化、淺拷貝深拷貝的奧秘

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.