成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JS面向?qū)ο缶幊讨庋b

YFan / 1477人閱讀

摘要:在基于原型的面向?qū)ο蠓绞街?,對象則是依靠構(gòu)造函數(shù)和原型構(gòu)造出來的。來看下面的例子優(yōu)點(diǎn)與單純使用構(gòu)造函數(shù)不一樣,原型對象中的方法不會在實(shí)例中重新創(chuàng)建一次,節(jié)約內(nèi)存。

我們所熟知的面向?qū)ο笳Z言如 C++、Java 都有類的的概念,類是實(shí)例的類型模板,比如Student表示學(xué)生這種類型,而不表示任何具體的某個學(xué)生,而實(shí)例就是根據(jù)這個類型創(chuàng)建的一個具體的對象,比如zhangsan、lisi,由類生成對象體現(xiàn)了抽象模板到具體化的過程,這叫做基于類的面向?qū)ο蠓绞?/strong>,而 JavaScript 沒有類的概念,是基于原型的面向?qū)ο蠓绞?/strong>(雖然 Es6 增加了 class,實(shí)質(zhì)是對原型方式的封裝)??偨Y(jié)起來就是以下兩點(diǎn):

在基于類的面向?qū)ο蠓绞街?,對象(object)依靠類(class)來產(chǎn)生。

在基于原型的面向?qū)ο蠓绞街?,對象(object)則是依靠構(gòu)造函數(shù)(constructor)和原型(prototype)構(gòu)造出來的。

面向?qū)ο笳Z言的第一個特性毫無疑問是封裝,在 JS 中,封裝的過程就是把一些屬性和方法放到對象中“包裹”起來,那么我們要怎么去封裝屬性和方法,或者說怎么去創(chuàng)建對象呢(后文統(tǒng)一說創(chuàng)建對象)?下面用逐步推進(jìn)的方式闡述:

對象字面量 --> 工廠模式 --> 構(gòu)造函數(shù) --> 原型模式 --> 構(gòu)造函數(shù)+原型模式
對象字面量

JS中創(chuàng)建對象最原始的方式有兩種:

對象字面量

var  person = {
    name: "leon",
    age: "20",

    greeting: function() {
      alert("Hi!");
    }
}

Object實(shí)例添加屬性方法

var person = new Object();
person.name = "leon";
person.age = "20";

person.greeting = function() {
  alert("Hi!");
};

優(yōu)點(diǎn):代碼簡單

缺點(diǎn): 創(chuàng)建多個對象會產(chǎn)生大量的代碼,編寫麻煩,且并沒有實(shí)例與原型的概念。

解決辦法:工廠模式。

工廠模式

工廠模式是編程領(lǐng)域一種廣為人知的設(shè)計模式,它抽象了創(chuàng)建具體對象的過程。JS 中創(chuàng)建一個函數(shù),把創(chuàng)建新對象、添加對象屬性、返回對象的過程放到這個函數(shù)中,用戶只需調(diào)用函數(shù)來生成對象而無需關(guān)注對象創(chuàng)建細(xì)節(jié),這叫工廠模式:

function createPerson(name, age) {
  var person = new Object();
  person.name = name;
  person.age = age;

  person.greeting = function() {
    alert("Hi!");
  };
  return person;
}

var person1 = createPerson("leon", "20");

優(yōu)點(diǎn):工廠模式解決了對象字面量創(chuàng)建對象代碼重復(fù)問題,創(chuàng)建相似對象可以使用同一API。

缺點(diǎn):因?yàn)槭钦{(diào)用函創(chuàng)建對象,無法識別對象的類型。

解決辦法:構(gòu)造函數(shù)

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

JS 中構(gòu)造函數(shù)與其他函數(shù)的唯一區(qū)別,就在于調(diào)用它的方式不同。任何函數(shù),只要通過new 操作符來調(diào)用,那它就可以作為構(gòu)造函數(shù)。來看下面的例子:

function Person(name, age) {
  this.name = name;
  this.age = age;
  
  this.greeting = function() {
    alert("Hi!");
  };
  // return this;
}

var person1 = new Person("leon", "20");
var person2 = new Person("jack", "21");

通過構(gòu)造函數(shù)new一個實(shí)例經(jīng)歷了四步:

創(chuàng)建一個新對象;

將構(gòu)造函數(shù)內(nèi)的this綁定到新對象上;

為新對象添加屬性和方法;

返回新對象(JS 引擎會默認(rèn)添加 return this;)。

而通過構(gòu)造函數(shù)創(chuàng)建的對象都有一個constructor屬性,它是一個指向構(gòu)造函數(shù)本身的指針,因此就可以檢測對象的類型啦。:

alert(person1.constructor === Person) //true
alert(person1 instanceof Person) // true

但是仍然存在問題:

alert(person1.greeting == person2.greeting) //false

同一個構(gòu)造函數(shù)中定義了greeting(),而不同實(shí)例上的同名函數(shù)卻是不相等的,意味著這兩個同名函數(shù)的內(nèi)存空間不一致,也就是構(gòu)造函數(shù)中的方法要在每個實(shí)例上重新創(chuàng)建一次。這顯然是不劃算的。

優(yōu)點(diǎn):解決了類似對象創(chuàng)建問題,且可以檢測對象類型。

缺點(diǎn):構(gòu)造函數(shù)方法要在每個實(shí)例上新建一次。

解決辦法:原型模式。

原型模式

終于講到了原型模式,JS 中每個構(gòu)造函數(shù)都有一個prototype屬性,這個屬性是一個指針,指向原型對象,而這個原型對象包含了這個構(gòu)造函數(shù)所有實(shí)例共享的屬性和方法。而實(shí)例對象中有一個proto屬性,它指向原型對象,也就是構(gòu)造函數(shù).prototype == 原型對象 == 對象._proto_,那么對象就可以獲取到原型對象中的屬性和方法啦。同時,所有對象中都有一個constructor屬性,原型對象的constructor指向其對應(yīng)的構(gòu)造函數(shù)。

使用原型,就意味著我們可以把希望實(shí)例共享的屬性和方法放到原型對象中去,而不是放在構(gòu)造函數(shù)中,這樣每一次通過構(gòu)造函數(shù)new一個實(shí)例,原型對象中定義的方法都不會重新創(chuàng)建一次。來看下面的例子:

function Person() {
}

Person.prototype.name = "leon";
Person.prototype.age = "20";
Person.prototype.greeting = function() {
  alert("Hi!");
};

var person1 = new Person();
var person2 = new Person();
alert(person1.name); //"leon"
alert(person2.name); //"leon"
alert(person1.greeting == person2.greeting); //true

優(yōu)點(diǎn):與單純使用構(gòu)造函數(shù)不一樣,原型對象中的方法不會在實(shí)例中重新創(chuàng)建一次,節(jié)約內(nèi)存。

缺點(diǎn):使用空構(gòu)造函數(shù),實(shí)例 person1 和 person2 的 name都一樣了,我們顯然不希望所有實(shí)例屬性方法都一樣,它們還是要有自己獨(dú)有的屬性方法。并且如果原型中對象中有引用類型值,實(shí)例中獲得的都是該值的引用,意味著一個實(shí)例修改了這個值,其他實(shí)例中的值都會相應(yīng)改變。

解決辦法:構(gòu)造函數(shù)+原型模式組合使用。

另外 JS 中還定義了一些與原型相關(guān)的屬性,這里羅列一下:

Object.getPrototypeOf(),取得實(shí)例的原型對象。

Object.getPrototypeOf(person1);

isPrototypeOf(),判斷是不是一個實(shí)例的原型對象。

Person.prototype.isPrototypeOf(person1);

hasOwnProperty(),檢測一個屬性是否存在于實(shí)例中

person1.hasOwnProperty("name");

in,判斷一個屬性是否存在于實(shí)例和原型中。

"name" in person1;
構(gòu)造函數(shù)+原型模式

最后一種方式就是組合使用構(gòu)造函數(shù)和原型模式,構(gòu)造函數(shù)用于定義實(shí)例屬性,而共享屬性和方法定義在原型對象中。這樣每個實(shí)例都有自己獨(dú)有的屬性,同時又有對共享方法的引用,節(jié)省內(nèi)存。

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

Person.prototype = {
  constructor: Person,
  nationality: "China",
  greeting: function() {
    alert(this.name);
  }
}

var person1 = new Person("leon", "20");
var person2 = new Person("jack", "21");
alert(person1.greeting == person2.greeting) //true

上面代碼中用對象字面量的形式重寫了原型對象,這樣相當(dāng)于創(chuàng)建了一個新的對象,那么它的constructor屬性就會指向Object,這里為了讓它繼續(xù)指向構(gòu)造函數(shù),顯示的寫上了constructor: Person

這種構(gòu)造函數(shù)與原型模式混成的模式,是目前在 JS 中使用最為廣泛的一種創(chuàng)建對象的方法。

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/96489.html

相關(guān)文章

  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對象”還好嗎?

    摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍(lán)圖或原型。在中,對象通過對類的實(shí)體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    李昌杰 評論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對象”還好嗎?

    摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍(lán)圖或原型。在中,對象通過對類的實(shí)體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    Lyux 評論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對象”還好嗎?

    摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍(lán)圖或原型。在中,對象通過對類的實(shí)體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    AaronYuan 評論0 收藏0
  • JS面向對象一 【概述】

    摘要:更形象的我們還可以將面向?qū)ο罄斫鉃橐环N宗教信仰。這就導(dǎo)致面向?qū)ο蠼痰某绦騿T們在寫時就很難受。所以為了滿足信仰面向?qū)ο蠼痰男枨笸ㄟ^構(gòu)造函數(shù)的形式模擬了偽類。這個套路的核心就是類那么里沒有類所以其實(shí)是通過構(gòu)造函數(shù)來模擬的偽類。 JS面向?qū)ο笾?【概述】 在學(xué)習(xí)JS的面向?qū)ο笾?我們應(yīng)該先自問這樣幾個問題: 面向?qū)ο笫鞘裁匆馑? 學(xué)習(xí)面向?qū)ο蟮暮诵氖鞘裁? 為什么要學(xué)習(xí)面向?qū)ο?(它的...

    JohnLui 評論0 收藏0
  • 如何在前端代碼中,應(yīng)用面向對象編程范式?

    摘要:為什么要面向?qū)ο竽阈枰赖拿嫦驅(qū)ο竺嫦驅(qū)ο蟛⒉皇轻槍σ环N特定的語言,而是一種編程范式。后端傳遞過來顯示工人完成狀態(tài)的字段代表未完成,代表已完成。其實(shí)這就是如何消除代碼副作用的問題將副作用隔離。 為什么要面向?qū)ο螅?你需要知道的面向?qū)ο?面向?qū)ο蟛⒉皇轻槍σ环N特定的語言,而是一種編程范式。但是每種語言在設(shè)計之初,都會強(qiáng)烈地支持某種編程范式,比如面向?qū)ο蟮腏ava,而Javascript...

    NeverSayNever 評論0 收藏0

發(fā)表評論

0條評論

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