成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

讀書筆記--對(duì)象、實(shí)例、原型、繼承

LuDongWei / 1487人閱讀

創(chuàng)建對(duì)象的設(shè)計(jì)模式

工廠模式

抽象了創(chuàng)建具體對(duì)象的過程,用函數(shù)封裝以特定接口創(chuàng)建對(duì)象的細(xì)節(jié)

解決了創(chuàng)建多個(gè)相似對(duì)象的問題,沒有解決對(duì)象識(shí)別的問題

function createPerson(name,age){
  var obj = new Object();
  obj.name = name;
  obj.age = age;
  obj.sayName = function(){
    alert(this.name)
  }

return obj;
}

var person = createPerson("aa",12);

構(gòu)造函數(shù)模式

構(gòu)造函數(shù)可以用來創(chuàng)建特定類型的對(duì)象,可以用instanceof檢測類型

使用new操作符會(huì)經(jīng)歷以下四個(gè)步驟

創(chuàng)建一個(gè)新對(duì)象

將構(gòu)造函數(shù)的作用域賦給新對(duì)象(因此this指向了這個(gè)新對(duì)象)

執(zhí)行構(gòu)造函數(shù)中的代碼(為這個(gè)新對(duì)象添加屬性)

返回新對(duì)象

缺點(diǎn):

每個(gè)方法都要在每個(gè)實(shí)例上重新創(chuàng)建一遍

每個(gè)方法(函數(shù))就是一個(gè)對(duì)象,不同實(shí)例上的同名函數(shù)是不相等的

將函數(shù)抽離到外部使多個(gè)對(duì)象共共享全局作用域的函數(shù)雖然可以解決上面問題,但讓this.sayName = sayName全局方法會(huì)破壞了對(duì)象的封裝性

function Person(name,age){
  this.name = name;
  this.age = age;
  this.sayName = function(){
    alert(this.name)
  }
}

var person = new Person("aa",12);

person instanceof Person => true
原型模式

prototype

只要?jiǎng)?chuàng)建了一個(gè)新函數(shù),就會(huì)為函數(shù)創(chuàng)建一個(gè)prototype屬性,這個(gè)屬性指向函數(shù)的原型對(duì)象

包含了特定類型的所有對(duì)象實(shí)例共享的方法和屬性

prototype是通過調(diào)用構(gòu)造函數(shù)而創(chuàng)建的那個(gè)對(duì)象實(shí)例的原型對(duì)象

默認(rèn)情況下所有原型對(duì)象會(huì)獲得一個(gè)constructor(構(gòu)造函數(shù)屬性),這個(gè)屬性指向prototype屬性所在函數(shù)的指針

當(dāng)調(diào)用構(gòu)造函數(shù)創(chuàng)建一個(gè)新實(shí)例時(shí),內(nèi)部將包含一個(gè)指針,指向原型對(duì)象,連接實(shí)例與原型對(duì)象

function Person(name,age){
 
}
Person.prototype.name = name;
Person.prototype.age = age;
Person.prototype.sayName = function(){
    alert(this.name)
  }
var person = new Person("aa",12);

person instanceof Person => true

判斷原型對(duì)象

Person.prototype.isPropertyOf(person) => true

Object.getPropertyOf(person) == Person.prototype => true (es5)

多個(gè)對(duì)象實(shí)例共享原型所保存的屬性和方法的基本原理

每當(dāng)代碼讀取某個(gè)對(duì)象的某個(gè)屬性時(shí),搜索從對(duì)象實(shí)例本身開始,如果在實(shí)例中找到具有給定名字的屬性則返回該屬性的值

如果沒有找到則繼續(xù)搜索指針指向的原型對(duì)象,如果在原型對(duì)象中找到給定名字的屬性,則返回這個(gè)值

雖然可以通過對(duì)象實(shí)例訪問保存在原型實(shí)例中的值,但是不能通過對(duì)象實(shí)例重寫原型中的值,如果在實(shí)例中添加一個(gè)與原型實(shí)例中的一個(gè)屬性同名,訪問時(shí)實(shí)例屬性會(huì)屏蔽原型中這個(gè)屬性的值,只能訪問到這個(gè)實(shí)例上屬性的值??梢酝ㄟ^delete操作符刪除實(shí)例屬性,重新訪問原型中的屬性

使用hasOwnProperty()可以檢測一個(gè)屬性是存在實(shí)例中還是原型中,只有存在實(shí)例中才會(huì)返回true;person.hasOwnProperty("name")

"name" in person 無論name是存在實(shí)例中還是原型對(duì)象中都會(huì)返回true

  //判斷對(duì)象原型上是否有這個(gè)屬性
  function hasPrototypeProperty(obj, attr){
    return (attr in obj) && !obj.hasOwnProperty(attr);
  }

在使用for-in 循環(huán)時(shí),返回的是能夠通過對(duì)象訪問的,可枚舉的屬性,包括了實(shí)例上的屬性和原型上的屬性。原型上不可枚舉的屬性,但是在實(shí)例中定義了也可以獲取得到,如在實(shí)例中定義toString

Object.keys() (es5)

取得對(duì)象上所有可枚舉的實(shí)例屬性,返回一個(gè)包含所有可枚舉的字符串?dāng)?shù)組

也可以傳入一個(gè)原型對(duì)象,Object.keys(Person.prototype),但不會(huì)沿著原型鏈往上尋找,只返回當(dāng)前prototype下的屬性

Object.getOwnPropertyNames()(ie9+)

枚舉所有實(shí)例屬性,不管是否可枚舉

原型的動(dòng)態(tài)性

在原型中查找值的過程是一次搜索,對(duì)原型 對(duì)象所做的任何修改都能立即從實(shí)例上反映出來--即使是先創(chuàng)建了實(shí)例后修改原型也照樣如此

  var friend = new Person();
  Person.prototype.sayHi = function(){
      
    alert("hi")
  }
  friend.sayHi() //hi

實(shí)例和原型之間松散的連接關(guān)系,可以隨時(shí)為原型添加屬性和方法,并且修改能夠立即在所有對(duì)象實(shí)例中反映出來

但是重寫整個(gè)原型對(duì)象就不一樣了,調(diào)用構(gòu)造函數(shù)時(shí)會(huì)為實(shí)例添加一個(gè)指向最初原型的[[prototype]]指針,而把原型修改為另外一個(gè)對(duì)象就等于切斷了構(gòu)造函數(shù)與最初原型的聯(lián)系

實(shí)例中的指針僅指向原型對(duì)象,而不指向構(gòu)造函數(shù)

  var friend = new Person();
  Person.prototype = {
    sayHi:function(){
      alert("hi")
    }
  }
  friend.sayHi() //error

原型模式的缺點(diǎn)

省略了為構(gòu)造函數(shù)傳遞初始化參數(shù),所有實(shí)例在默認(rèn)情況下都將取得相同的值

當(dāng)使用原型屬性時(shí)會(huì)只要在一個(gè)實(shí)例上修改都會(huì)影響到所有的實(shí)例,例如在一個(gè)實(shí)例上修改數(shù)組

組合使用構(gòu)造函數(shù)和原型模式

構(gòu)造函數(shù)定義實(shí)例屬性,原型模式定義方法和屬性

動(dòng)態(tài)原型模式

通過檢查某個(gè)應(yīng)該存在的方法是否有效,來決定是否需要初始化原型

 function Person(name,age){
  this.name = name;
  this.age = age;
  **if( typeof this.sayName != "funcction"){
     Person.prototype.sayName = function(){
      alert("hi")
    }
  }**
}

只有初次調(diào)用構(gòu)造函數(shù)時(shí)才會(huì)執(zhí)行將函數(shù)添加到原型中

寄生構(gòu)造函數(shù)模式

類似于工廠模式,封裝創(chuàng)建對(duì)象的代碼,然后返回新創(chuàng)建對(duì)象,return語句可以重寫調(diào)用構(gòu)造函數(shù)時(shí)返回的值

  function Person(name,age){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.sayName = function(){
      alert("hi");
    }
  return o;
  }

使用場景:特殊情況下用來為對(duì)象創(chuàng)造構(gòu)造函數(shù)。

假設(shè)創(chuàng)建一個(gè)具有額外方法的特殊數(shù)組,由于不能直接修改Array構(gòu)造函數(shù)

function SpecialArray(){
  var arr = new Array();
  arr.push.apply(values,arguments);
  arr.toPipedString = function(){
  return this.join("|");  
}
return arr;

colors = new SpecialArray("green","red");
colors.toPipedString()

缺點(diǎn):返回的對(duì)象和構(gòu)造函數(shù)或者與構(gòu)造函數(shù)的原型屬性之間沒有什么關(guān)系,不能使用instanceof來確定對(duì)象類型

穩(wěn)妥構(gòu)造函數(shù)模式

特點(diǎn)

新創(chuàng)建對(duì)象的實(shí)例方法不引用this

不使用new操作符調(diào)用構(gòu)造函數(shù)

除了返回對(duì)象上的屬性和方法,沒有其他辦法訪問到構(gòu)造函數(shù)內(nèi)的數(shù)據(jù)

function Person(name,age){
  var o = new Object();
  //這里可以定義私有數(shù)據(jù)
  o.sayName = function(){
    alert(name)
}
return o;

person = Person("green",12);
person.sayName() //只能通過sayName()方法去訪問name的值

繼承 原型鏈繼承

js以原型鏈作為實(shí)現(xiàn)繼承的主要方法

基本思想是利用原型鏈讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法

構(gòu)造函數(shù)、原型、實(shí)例的關(guān)系

每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象

原型對(duì)象都有一個(gè)指向構(gòu)造函數(shù)的方法

實(shí)例都包含一個(gè)指向原型對(duì)象的一個(gè)指針

function SuoperType(){
  this.property = true; 
}
SuperType.prototype.getSuperValue = function(){
  return this.property;
}
function SubType(){
  this.subproperty = false;
}
SubType.prototype = new SuperType();
SubType.prototype.getSubType = function(){
  return this.subprototype;
}
var instance = new SubType()
instance.getSuperValue();//true

SubType不僅具有作為一個(gè)SuperType的實(shí)例所擁有的全部屬性和方法,而且擁有一個(gè)指向SuperType原型的指針

instance指向SubType原型,SubType原型又指向SuperType的原型

確定實(shí)例與原型的關(guān)系

instanceof操作符 只要用這個(gè)操作符來測試實(shí)例與原型中出現(xiàn)過的構(gòu)造函數(shù),結(jié)果就會(huì)返回true

isPropertyOf() 只要是原型鏈中出現(xiàn)的原型,都可以說是該原型鏈所派生的實(shí)例的原型,都會(huì)返回true

缺點(diǎn):

原型屬性會(huì)被所有實(shí)例共享,如果在父構(gòu)造函數(shù)中有一個(gè)this.colors=[]的數(shù)組,子構(gòu)造函數(shù)繼承后的實(shí)例可以修改這個(gè)存在于子構(gòu)造函數(shù)原型對(duì)象上的原型屬性

在創(chuàng)建子類型的實(shí)例時(shí),不能向超類型的構(gòu)造函數(shù)傳遞參數(shù)。實(shí)際上是沒有辦法在不影響所有實(shí)例的情況下給超類型的構(gòu)造函數(shù)傳遞參數(shù)

借用構(gòu)造函數(shù)

在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù),通過call,apply 改變對(duì)象的this指向

function SuoperType(name){
  this.colors = ["red"]; 
  this.name = name;
}

function SubType(name){
  SuperType.call(this,name);
}
SubType.prototype = new SuperType();
var instance = new SubType("1")
instance.colors.push("green") => ["red","green"]

var instance2 = new SubType("2")
instance2.colors.push("black") => ["red","black"]
組合繼承

將原型鏈和借用構(gòu)造函數(shù)的技術(shù)組合到一起

使用原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承

使用借用構(gòu)造函數(shù)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承

function SuperType(name){
  this.colors = ["red"]; 
  this.name = name;
}
SuperType.prototype.sayName = function(){
  alert(this.name)
}
function SubType(name,age){
  SuperType.call(this,name);
  this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayName = function(){
  alert(this.name)
}
var instance = new SubType("1",12)
instance.sayName() => 1
instance.colors => ["red"]
var instance2 = new SubType("2",21)
instance2.sayName() => 2
instance2.colors => ["red"]
原型式繼承

基于一個(gè)對(duì)象上,這個(gè)對(duì)象相當(dāng)于作為原型,再根據(jù)需求對(duì)得到的對(duì)象加以修改

在沒有必要興師動(dòng)眾創(chuàng)建構(gòu)造函數(shù),而只想讓一個(gè)對(duì)象與另一個(gè)對(duì)象保持類似的情況下使用

  function object(o) {
    function F(){}
    F.prototype = o;
    return new F();
  }
  var person = {
    name:"n",
    friends:["a","b"]
  }
  var anotherPerson = object(person);
  anotherPerson.name = "y";  =>y
  anotherPerson.colors.push("c");  => ["a","b","c"]
  var person = object(person);
 person.name = "yy";  =>yy
person.color; =>["a","b","c"]

Object.create() es5新增規(guī)范原型式繼承

var person = {
 name:"n",
 friends:["a","b"]
}
var anotherPerson = Object.create(person);
anotherPerson.name = "y";  =>y
anotherPerson.colors.push("c");  => ["a","b","c"]
var person =  Object.create(person);
person.name = "yy";  =>yy
person.color; =>["a","b","c"]

寄生式繼承

創(chuàng)建一個(gè)僅用于封裝繼承過程的函數(shù),在函數(shù)內(nèi)部以某種方式增強(qiáng)對(duì)象

  function object(o) {
    function F(){}
    F.prototype = o;
    return new F();
  }
  function createAnother(original){
    var clone = object(original);
    clone.sayHi = function(){
      alert("hi")
    }
  return clone;
  }
  var person = {
    name:"n",
    friends:["a","b"]
  }
  var anotherPerson = createAnother(person);
  anotherPerson.sayHi(); =>hi
寄生組合式繼承

組合繼承最大的問題是無論什么情況下都會(huì)調(diào)用兩次超類型構(gòu)造函數(shù)

一次是創(chuàng)建子類型原型時(shí),一次是子函數(shù)的內(nèi)部構(gòu)造函數(shù)

寄生組合繼承通過借用構(gòu)造函數(shù)來繼承屬性,通過原型鏈混成形式來繼承方法。

思路是不必為了指定的子類型原型而調(diào)用超類型的構(gòu)造函數(shù)。

使用寄生式繼承來繼承超類型的原型,然后再將結(jié)果指定給子類型的原型

    function inheritPrototype(subType,superType){
      var prototype = object(superType);
      prototype.constructor = subType;
      subType.prototype = prototype;
  }

function SuperType(name){
  this.colors = ["red"]; 
  this.name = name;
}
SuperType.prototype.sayName = function(){
  alert(this.name)
}
function SubType(name,age){
  SuperType.call(this,name);
  this.age = age;
}
SubType.prototype =inheritPrototype(subType,superType) ;
SubType.prototype.sayName = function(){
  alert(this.name)
}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/87944.html

相關(guān)文章

  • 《javascript高級(jí)程序設(shè)計(jì)》第六章 讀書筆記 之 javascript繼承的6種方法

    摘要:繼承的是超類型中構(gòu)造函數(shù)中的屬性,如上繼承了屬性,但沒有繼承原型中的方法。上述造成的結(jié)果是子類型實(shí)例中有兩組超類型的構(gòu)造函數(shù)中定義的屬性,一組在子類型的實(shí)例中,一組在子類型實(shí)例的原型中。 ECMAScript只支持實(shí)現(xiàn)繼承,主要依靠原型鏈來實(shí)現(xiàn)。與實(shí)現(xiàn)繼承對(duì)應(yīng)的是接口繼承,由于script中函數(shù)沒有簽名,所以無法實(shí)現(xiàn)接口繼承。 一、原型鏈 基本思想:利用原型讓一個(gè)引用類型繼承另一個(gè)引用...

    孫吉亮 評(píng)論0 收藏0
  • Javascript 設(shè)計(jì)模式讀書筆記(三)——繼承

    摘要:的繼承方式屬于原型式繼承,非常靈活。當(dāng)使用關(guān)鍵字執(zhí)行類的構(gòu)造函數(shù)時(shí),系統(tǒng)首先創(chuàng)建一個(gè)新對(duì)象,這個(gè)對(duì)象會(huì)繼承自構(gòu)造函數(shù)的原型對(duì)象新對(duì)象的原型就是構(gòu)造函數(shù)的屬性。也就是說,構(gòu)造函數(shù)用來對(duì)生成的新對(duì)象進(jìn)行一些處理,使這個(gè)新對(duì)象具有某些特定的屬性。 繼承這個(gè)東西在Javascript中尤其復(fù)雜,我掌握得也不好,找工作面試的時(shí)候在這個(gè)問題上栽過跟頭。Javascript的繼承方式屬于原型式繼承,...

    cangck_X 評(píng)論0 收藏0
  • JS高程讀書筆記--第六章原型繼承

    摘要:高程讀書筆記第六章理解對(duì)象創(chuàng)建自定義對(duì)象的方式有創(chuàng)建一個(gè)實(shí)例,然后為它添加屬性和方法。創(chuàng)建了自定義的構(gòu)造函數(shù)之后,其原型對(duì)象默認(rèn)只會(huì)取得屬性至于其他方法都是從繼承而來的。 JS高程讀書筆記--第六章 理解對(duì)象 創(chuàng)建自定義對(duì)象的方式有創(chuàng)建一個(gè)Object實(shí)例,然后為它添加屬性和方法。還可用創(chuàng)建對(duì)象字面量的方式 屬性類型 ECMAScript在定義只有內(nèi)部采用的特性時(shí),描述了屬性的各種特征...

    EasonTyler 評(píng)論0 收藏0
  • 讀書筆記(02) - 可維護(hù)性 - JavaScript高級(jí)程序設(shè)計(jì)

    摘要:解耦優(yōu)勢代碼復(fù)用,單元測試。常用比較誤區(qū)可同時(shí)判斷,可用來判斷對(duì)象屬性是否存在。使用作判斷無法進(jìn)行充分的類型檢查。文件中應(yīng)用常量參考文檔高級(jí)程序設(shè)計(jì)作者以樂之名本文原創(chuàng),有不當(dāng)?shù)牡胤綒g迎指出。 showImg(https://segmentfault.com/img/bVburXw?w=500&h=400); 編寫可維護(hù)性代碼 可維護(hù)的代碼遵循原則: 可理解性 (方便他人理解) 直觀...

    k00baa 評(píng)論0 收藏0
  • 讀書筆記-1【javascript語言精粹】繼承

    摘要:使用構(gòu)造器有個(gè)嚴(yán)重的危害,如果在調(diào)用構(gòu)造器函數(shù)的時(shí)候忘記使用前綴,不僅不會(huì)綁定到新對(duì)象,還會(huì)污染全局變量原型模式原型模式中,我們采用對(duì)象來繼承。 構(gòu)造器調(diào)用模式 當(dāng)一個(gè)函數(shù)對(duì)象被創(chuàng)建時(shí),F(xiàn)unction構(gòu)造器會(huì)運(yùn)行類似這樣的代碼: this.prototype = {constructor: this} new一個(gè)函數(shù)事會(huì)發(fā)生: Function.method(new, functio...

    malakashi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<