国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

創建對象(一):創建與繼承

microelec / 2217人閱讀

摘要:創建實例的方式有三種對象字面量表示法操作符跟構造函數中的函數。下面主要講的是最為復雜的操作符跟構造函數的創建對象實例的方法。

創建對象 一.創建對象的方法

理解原型對象:

無論什么時候,只要創建了新函數,就會根據一組特定的規則為該函數創建一個 prototype屬性,這個屬性指向函數的原型對象。在默認情況下,所有原型對象都會自動獲得一個constructor屬性,這個屬性包含一個指向prototype屬性的所在函數的指針。(重寫原型屬性會默認取消constructor屬性)詳細可見文章下圖。

創建object實例的方式有三種:對象字面量表示法、new操作符跟object構造函數、(ECMAScrript5中的)object.create()函數。下面主要講的是最為復雜的new操作符跟object構造函數的創建對象實例的方法。

1.1工廠模式

function createPerson(name,age,job){
    var o=new Object();//創建對象實例
        o.name=name;//為對象實例添加屬性
        o.age=age;
        o.job=job;
        o.sayName=function(){
            alert(this.name);
        }
    return o;//返回剛創建的對象實例
}
var person1= createPerson("NIcho",29,"software engineer");

工廠模式的問題:

工廠模式雖然解決了創建多個相似對象的問題,但是沒有解決對象識別的的問題(即怎樣知道一個對象的類型)。

1.2.構造函數模式
應用:創建對象的自有屬性的主要方法,每定義一個函數就實例化了一個對象.
function Person(name,age,job){

    this.name=name;
    this.age=age;
    this.job=job;
    this.sayName=function(){
        alert(this.name);

}

//將構造的函數Person實例化,傳入的參數作為自有屬性,并且繼承自Person.prototype
var person1=new Person(NIcho",29,"software engineer);
var person2=new Person(Jhon",26,"software engineer);

注意:1.alert(Person.name);//undefined
Person函數代替了createPerson函數,還有以下不同之處:
(1)沒有顯式創建對象
(2)直接將屬性和方法賦給this對象(這里的this指的就是這個構造的函數)
(3)沒有return 語句
我們在這個例子中創建的對象既是object的實例又是person的實例(所有對象均繼承自object。object可以理解為對象的根原型,我們所用到的所有對象方法的操作,如toString 、substring 、splice等都是繼承自object)

alert(person1 instanceOf Object);//true
alert(person1 instanceOf Person);//true

構造函數模式的問題:

使用構造函數的主要問題是,每個方法都要在每個實例上創建一次。person1和person2都有一個sayName的方法,但兩個方法不是同一個Function實例(ECMAScript中的函數是對象,每定義一個函數就是實例化了一個對象)。

如果沒有自定義向person原型中添加屬性,實例化之后則得到Person自有屬性的一個副本,并且繼承object。(注:person1與person2中sayName()引用位置不同)

                         圖1構造函數模式下的實例化對象

通過把函數定義轉移到構造函數外來解決:

//全局函數
function sayName(){
    alert(this.name);
}

對應的:this.syName:sayName;

1.3原型模式
應用:用于定義實例共享的屬性和方法

function Person(){
}
Person.prototype.name="Nicho";
Person.prototype.age=29;
Person.prototype.jod="software engineer";
Person.prototype.sayName=function(){alert(this.name)};
var person1=new Person();
person1.sayName();//"Nicho" 繼承Person.prototype
var person2=new Person();
person2.sayName();//"Nicho"繼承Person.prototype
alert(person1.sayName==person2.sayName);//true 引用位置相同

                            圖2 person1、person2繼承自person.prototype

(注:繼承連接存在與實例與構造函數的原型之間而不是實例與構造函數之間)

關于原型上的一些函數:

1.檢測obj是否為obj1的原型:obj.isPrototypeOf(obj1)//返回true/false
2.獲得obj1的原型:object.getPrototypeOf(obj1)
3.檢測一個屬性是否存在于實例中(也就是自有屬性)還是原型中(來自于繼承):
Obj1.hasOwnProperty();//如果obj1有自有屬性則返回true,否則返回false

1.4組合使用構造函數模式和原型模式
組合使用構造函數模式和原型模式既可以繼承原型對象的屬性,又可以設置自由屬性

function Person(name,age,job){
        this.name=name;
        this.age=age;
        this.job=job;
}
Person.prototype={
    constructor:Person,
    sayName:function(){
        alert("Hi");
    }
   }
var person1=new Person(“Nicho”,29,”software engineer”);
//person1自有屬性:name aga job;原型屬性(來自繼承):constructor sayName

代碼讀取某個對象的某個屬性時的搜索方法:

搜索首先從對象實例開始,如果實例中找到了給定名字的屬性,則返回該屬性的值。如果沒有找到,則繼續搜索指針指向的原型對象,在原型對象中查找給定名字的屬性。如果在原型對象中找到了該屬性,則返回屬性的值,否則一直向上查找給定名字的屬性,直到object。如果沒有找到則返回undefined。

這就需要我們注意:雖然我們可以通過對象實例訪問原型中的值,但卻不能通過對象實例(注意!!這里說的是通過對象實例而不是在原型中修改屬性)來重寫原型中的值。如果在實例中添加了一個與實例原型中同名的屬性,該屬性將會屏蔽原型中的那個屬性。來看下面的的例子:

function Person(){

}
Person.prototype.name="Nicho";
Person.prototype.age=29;
Person.prototype.jod="software engineer";
Person.prototype.sayName=function(){alert(this.name)};
var person1=new Person();
var person2=new Person();
 person1.name="Greg";
alert(person1.name);//Greg-來自實例
alert(person2.name);//Nicho-來自原型;
//person1對屬性 name的修改并不能修改原型上的相應屬性,因此person2繼承自原型

1.person1=new Person()與 person3=person1是不同的:前者是實例化一個對象,
后者遵循復制函數(對象引用)的原理
2.對對象整體進行操作(引用)和對對象中的某個屬性(值)進行操作實現原理是不同的
1). 整個對象的復制即引用相同

var person3=person1;//整個對象的復制即引用相同(指針指針指針!只是一個索引,實際存儲都不在指針位置下)
person3.name=”newName”;//修改屬性名稱的值
alert(person1.name);//newName;//另一個來自此處的引用屬性的值會修改;即復制對象原理
alert(person1.isPrototypeOf(person3));//false
alert(Person.prototype.isPrototypeOf(person3));//true

2).簡單的屬性的復制,并非引用同一個屬性值.

var person1=new Person("NIcho",29,"software engineer");
  var person2=new Person("HIcho",9,"Hardware engineer");
  person1.name=person2.name;//簡單的屬性的復制,并非引用同一個屬性值
  person2.name="NEW";//嘗試賦新值
  alert(person1.name);//HIcho,說明是值的傳遞而并非引用
二.繼承

1.ECMAScript只支持實現繼承,而且實現繼承主要是依靠原型鏈來實現的。
2.其基本思想是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法。(即:原型鏈的構建是通過將一個類型的實例賦值給另一個構造函數的原型來實現的)

2.1原型鏈的繼承

function superType(){
    this.property=true;
   }
    superType.prototype.getSuperValue=function(){
        return this.property;
    };
    function subType(){
        this.subProperty=false;
    }
    //繼承superType
    subType.prototype=new superType();
    subType.prototype.getSubValue=function(){
        return this.subProperty;
    };
    var instance=new subType();
    alert((instance.getSuperValue)());//true  getSuperValue來自superType.prototype
    alert(instance.property);//true   property來自superType實例
    

實現的本質是重寫原型對象,代之以一個新類型的實例。換句話說,原來存在于superType的實例的所有屬性和方法(包括自有屬性和繼承屬性),現在也存在于subType.prototype中了。

                        圖4 subType繼承了superType 

(此時instance.constructor現在指向的是superType,因為subType的原型指向了另一個對象superType的原型,而這個原型對象的constructor指向的是superType)

注意:
1.別忘記默認的對象Object.prototype: subType繼承了superType,superType繼承了Object.prototype

確定原型和實例的關系:

(1)instanceOf;測試實例與原型鏈中出現過的構造函數

alert(instance instanceOf  superType);//true
alert(instance instanceOf  subType);//true

(2)isPrototypeOf:只要原型鏈中出現過的原型都可以說是該原型鏈所派生出來的實例的原型

alert(superType.protoType.isPrototypeOf (instance));//true
alert(subType.protoType.isPrototypeOf (instance));//true

原型鏈的問題:
在通過原型來實現繼承時,原型實際上會變成另一個類型的實例。于是,原先的實例屬性也就順理成章地變成了現在的原型屬性了。

2.2解決原型鏈繼承帶來的問題的方法

解決這個問題的技術是借用構造函數,使用最多的繼承模式是組合繼承。此外還有原型式繼承,寄生式繼承,寄生組合繼承。這里主要講借用構造函數和組合繼承。

(1)借用構造函數
//在子類型構造函數的內部調用超類型的構造函數

function superType(){
    this.colors=["red","blue","green"];
  }
  function subType(){
    //繼承了superType
    superType.call(this);//在新創建的subType實例的環境下調用superType函數
    //這樣一來,就會在新subType對象上執行superType函數中定義的所有初始化代碼
    //結果subType的每一個實例都會具有自己的color屬性的副本了
  }
  var instance1=new subType();
  instance1.colors.push("black");
  alert(instance1.colors);//red,blue,green,black
  var instance2=new subType();
  alert(instance2.colors);//red,blue,green

(2)組合繼承
思路是使用原型鏈實現對屬性和方法的繼承,而通過借用函數來實現對實例屬性的繼承

function superType(name){//超類中定義,為以后繼承該實例屬性(子類的原型)做準備
    this.name=name;
    this.colors=["red","blue","green"];
  }
superType.prptotype.sayName=function(){
alert(this.name);
}// superType.prptotype新增屬性,位于繼承的更高層
function subtype(name,age){//創建自有屬性
superType.call(this,name); //繼承屬性式的創建
this.age=age;//直接新增
}
//繼承方法
subtype.prototype=new superType();
subtype.prototype.constructor=subtype;
subtype.prototype.sayAge=function(){//subtype.prototype為自己新增方法
alert(this.age);
}
var instance1=new subType(“Nicho”,29);
  instance1.colors.push("black");
  alert(instance1.colors);//red,blue,green,black
instance1.sayName();//”Nicho”
instance1.sayAge();//29

  var instance2=new subType(“Greg”,27);
  alert(instance2.colors);//red,blue,green
instance2.sayName();//”Greg”
instance2.sayAge();//27

總結:
1.subType的自有屬性: this.age=age

2.subType的繼承屬性:
(1)superType.prptotype.sayName 、subtype.prototype.sayAge
(2)function superType(name){

this.name=name;
        this.colors=["red","blue","green"];
          }

3.
下面讓我們看下一種情況:重寫原型對象(完全重寫而不是簡單的添加原型對象的屬性)
我們知道,在調用構造函數是會為實例添加一個prototype指針,而把這個原型修改為另一個對象就等于切斷了構造函數與最初原型之間的聯系。請記住:實例中的指針僅指向原型而不指向構造函數。

function Person(){};
var friend=new Person();
Person.prototype={
Constructor:Person,
Name:“Nicholas”,
Age:29,
sayName=function(){
alert(“this.name”);
}
}
friend.sayName();//error

重寫原型對象之前:

重寫原型對象之后:

由圖可見:重寫原型對象切斷了現有原型與任何之前已經存在的對象實例之間的聯系,它們引用的仍是最初的原型

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/79098.html

相關文章

  • 徹底理解Javascript中的原型鏈繼承

    摘要:在節中,我們學習到了通過構造函數創建對象的三個重要步驟,其中的一步是把構造函數的對象設置為創建對象的原型。利用而不是直接用創建一個實例對象的目的是,減少一次調用父構造函數的執行。 JavaScript語言不像面向對象的編程語言中有類的概念,所以也就沒有類之間直接的繼承,JavaScript中只有對象,使用函數模擬類,基于對象之間的原型鏈來實現繼承關系,ES6的語法中新增了class關鍵...

    ziwenxie 評論0 收藏0
  • 前端進擊的巨人(七):走進面向對象,原型原型鏈,繼承方式

    摘要:除了以上介紹的幾種對象創建方式,此外還有寄生構造函數模式穩妥構造函數模式。 showImg(https://segmentfault.com/img/remote/1460000018196128); 面向對象 是以 對象 為中心的編程思想,它的思維方式是構造。 面向對象 編程的三大特點:封裝、繼承、多態: 封裝:屬性方法的抽象 繼承:一個類繼承(復制)另一個類的屬性/方法 多態:方...

    wums 評論0 收藏0
  • ES5-對象創建繼承----《JavaScript高程3》

    摘要:并且,在創建子類型的實例時,無法向超類型的構造函數傳遞參數。借用構造函數經典繼承在子類型構造函數的內部調用超類型構造函數。缺點是同樣具有構造函數模式創建對象的固有弊端構造函數中煩人方法函數對象重復創建。 創建對象的幾種方式 在邏輯上從低級到高級:工廠模式、構造函數模式、原型模式、組合模式。當然還有其他模式,但是這四者邏輯關系強,總結起來很有感覺。之所以和繼承一起分析,也是因為邏輯關系很...

    Heier 評論0 收藏0
  • JavaScript系列--淺析原型鏈繼承

    摘要:綜上所述有原型鏈繼承,構造函數繼承經典繼承,組合繼承,寄生繼承,寄生組合繼承五種方法,寄生組合式繼承,集寄生式繼承和組合繼承的優點于一身是實現基于類型繼承的最有效方法。 一、前言 繼承是面向對象(OOP)語言中的一個最為人津津樂道的概念。許多面對對象(OOP)語言都支持兩種繼承方式::接口繼承 和 實現繼承 。 接口繼承只繼承方法簽名,而實現繼承則繼承實際的方法。由于js中方法沒有簽名...

    draveness 評論0 收藏0
  • 面向對象的小九九

    摘要:由構造函數返回的對象就是表達式的結果。如果構造函數沒有顯式返回一個對象,則使用步驟創建的對象。運算符返回一個布爾值,表示對象是否為某個構造函數的實例。 面向對象 本人能力有限,有誤請斧正 本文旨在復習面向對象(不包含es6) 本文學習思維 創建對象的方式,獲取對象屬性 構造函數,構造函數的new 做了什么 原型與原型對象 原型鏈 繼承(借用構造繼承、原型繼承、組合繼承、寄生組合繼承)...

    時飛 評論0 收藏0

發表評論

0條評論

microelec

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<