国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【編程向?qū)А縅avaScript-創(chuàng)建對象一期講解

這篇具有很好參考價值的文章主要介紹了【編程向?qū)А縅avaScript-創(chuàng)建對象一期講解。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

工廠模式

工廠模式 是用來創(chuàng)建對象的一種最常用的設計模式。工廠模式不暴露創(chuàng)建對象的具體邏輯,而是將邏輯封裝在一個函數(shù)中,那么這個函數(shù)就可以被視為一個工廠。工廠模式常見于大型項目,例如 jQuery 的 $ 對象,我們創(chuàng)建選擇器對象之所以沒有 new selector 就是因為 $() 已經(jīng)是一個工廠方法,其他例子例如 React.createElement()Vue.component() 都是工廠模式的實現(xiàn)。

工廠模式根據(jù)抽象程度的不同可以分為三種:

  • 簡單工廠:通過第三方的類完成松耦合的任務
  • 復雜工廠:通過把實例化的任務交給子類來完成的,用以到達松耦合的目的
  • 超級工廠:通過 eval() 來完成智能工廠

工廠的目的:在于判斷接口最終用哪個類實例化(故與接口密不可分)。

使用工廠最終達到的效果是:多態(tài),和類與類之間的松耦合。

應用場景

ES5 實現(xiàn)工廠模式

function createPerson(name, age, job) {
  let person = new Object();
  person.name = name;
  person.age = age;
  person.job = job;
  person.sayNam = function () {
    console.log(`I'm ${name}`);
  };

  return person;
}

const person1 = createPerson('Ben', 21, 'student');
const person2 = createPerson('Gray', 25, 'Doctor');

函數(shù) createPerson() 能夠根據(jù)接受的參數(shù)來構(gòu)建一個包含所有必要信息的 Person 對象??梢詿o數(shù)次調(diào)用這個函數(shù),而每次它都會返回一個包含三個屬性一個方法的對象。工廠模式雖然解決了創(chuàng)建多個相似對象的問題,但卻沒有解決對象識別的問題(即怎樣知道一個對象的類型)。

ES6 實現(xiàn)工廠模式

class User {
  constructor(name, auth) {
    this.name = name;
    this.auth = auth;
  }
}
class UserFactory {
  static createUser(name, auth) {
    //工廠內(nèi)部封裝了創(chuàng)建對象的邏輯:
    //權(quán)限為 admin 時,auth=1;權(quán)限為 user 時,auth 為 2
    //使用者在外部創(chuàng)建對象時,不需要知道各個權(quán)限對應哪個字段, 不需要知道賦權(quán)的邏輯,只需要知道創(chuàng)建了一個管理員和用戶
    if (auth === 'admin') return new User(name, 1);
    if (auth === 'user') return new User(name, 2);
  }
}
const admin = UserFactory.createUser('cxk', 'admin');
const user = UserFactory.createUser('xz', 'user');

原型模式

我們創(chuàng)建的每個函數(shù)都有一個 prototype(原型)屬性,這個屬性是一個指針,指向一個對象,而這個對象的用途是包含可以由 特定類型的所有實例共享的屬性和方法。如果按照字面意思來理解,那么 prototype 就是通過調(diào)用構(gòu)造函數(shù)而創(chuàng)建的那個對象實例的原型對象。使用原型對象的好處是可以讓所有對象實例共享它所包含的屬性和方法。換句話說,不必在構(gòu)造函數(shù)中定義對象實例的信息,而是可以將這些信息直接添加到原型對象中。

function Person(){}

Person.prototype.name = 'Uzi';
Person.prototype.age = 22;
Person.prototype.job = 'E-Sports Player';
Person.prototype.sayName = function(){
  console.log(this.name);
}

const uzi1 = new Person();
uzi1.sayName();
// 'Uzi'

const uzi2 = new Person();
uzi2.sayName();
// 'Uzi'

// 共用公用方法
console.log(person1.sayName == person2.sayName);
// true

與構(gòu)造函數(shù)不同,新對象的這些屬性和方法是由所有實例共享的。

理解原型對象

無論什么時候,只要創(chuàng)建一個新函數(shù),就會根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個 prototype 屬性,這個屬性指向函數(shù)的原型對象。在默認情況下,所有原型對象都會自動獲得一個 constructor(構(gòu)造函數(shù))屬性,這個屬性是一個指向 prototype 屬性所在函數(shù)的指針。

創(chuàng)建了自定義的構(gòu)造函數(shù)之后,其原型對象默認只會取得 constructor 屬性;至于其他方法,則都是從 Object 繼承而來的。當調(diào)用構(gòu)造函數(shù)創(chuàng)建一個新的實例后,該實例的內(nèi)部將包含一個指針(內(nèi)部屬性),指向構(gòu)造函數(shù)的原型對象。ECMAScript 5 中管這個指針叫做 [[Prototype]]。雖然在腳本中沒有標準的方式訪問 [[Prototype]],但 Firefox、Safari 和 Chrome 在每個對象上都支持一個屬性 __proto__;而在其他實現(xiàn)中,這個屬性對腳本則是完全不可見的。不過,要明確的真正重要的一點就是,這個連接存在于實例與構(gòu)造函數(shù)的原型之間,而不是存在于實例與構(gòu)造函數(shù)之間。

原型最初只包含 constructor 屬性,而該屬性也是共享的,因此可以通過對象實例訪問。

雖然可以通過對象實例訪問保存在原型中的值,但卻不能通過對象實例重寫原型中的值。如果我們在實例中添加了一個屬性,而該屬性與實例原型中的一個屬性同名,那我們就在實例中創(chuàng)建該屬性,該屬性將會屏蔽原型中的屬性。

function Person(){}

Person.prototype.name = 'Nicholas';
Person.prototype.age = 29;
Person.prototype.job = 'Software Engineer';
Person.prototype.sayName = function(){
console.log(this.name);
};

const person1 = new Person();
const person2 = new Person();

person1.name = 'Greg';
console.log(person1.name);
// 'Greg' 		// from instance
console.log(person2.name);
// 'Nicholas' 	// from prototype

兩個實例訪問 name 屬性的過程:

  • person1 ==> 實例中讀取 name 屬性 ==> 在實例中讀取 name 屬性成功
  • person2 ==> 實例中讀取 name 屬性 ==> 實例中無 name 屬性 ==> 從原型鏈中讀取 name 屬性 ==> 讀取成功

當為對象實例添加一個屬性時,這個屬性就會 屏蔽 原型對象中保存的同名屬性。換句話說,添加這個屬性只會阻止我們訪問原型中的那個屬性值,但不會修改那個屬性。即使這個屬性設置為 null,也只會在實例中設置這個屬性,而不會恢復其指向原型的連接。不過,使用 delete 操作符則可以完全刪除實例屬性,從而讓我們能夠重新訪問原型中的屬性。

ECMAScript5 的 Object.getOwnPropertyDescriptor() 方法只能用于實例屬性,要取得原型屬性的描述符,必須直接在原型對象上調(diào)用 Object.getOwnPropertyDescriptor() 方法。

原型與實例屬性檢測

有兩種方式使用 in 操作符:單獨使用和在 for-in 循環(huán)中使用。在單獨使用時,in 操作符會在通過對象能夠訪問給定屬性時返回 true,無論該屬性存在于實例中還是原型中。

同時使用 hasOwnProperty() 方法和 in 操作符,就可以確定該屬性到底是存在于對象中,還是存在于原型中。

由于 in 操作符只要通過對象能夠訪問到屬性就返回 true,hasOwnProperty() 只在屬性存在于實例中時才返回 true,因此只要 in 操作符返回 truehasOwnProperty() 返回 false,就可以確定屬性是原型中的屬性。

更簡單的原型語法

前面的例子中每添加一個屬性和方法就要輸入一遍 Person.prototype,為減少不必要的輸入,也為了從視覺上更好地封裝原型的功能,更常見的做法是用一個包含所有屬性和方法的對象字面量來重寫整個原型對象。

function Person(){}

Person.prototype = {
  name: 'Nicholas',
  age: 29,
  job: 'Software Engineer',
  sayName: function (){
    console.log(this.name);
  }
}

前面介紹過,沒創(chuàng)建一個函數(shù),就會同時創(chuàng)建它的原型對象,這個對象自動獲得構(gòu)造函數(shù)。而這里的語法,這里相當于重寫了實例的原型對象,相應地原型對象中的構(gòu)造函數(shù) constructor 亦被覆蓋,不再指向 Person 函數(shù)。此時,盡管 instanceof 操作符還能返回正確的結(jié)果,但通過 constructor 已經(jīng)無法確定對象的類型了。

當然,我們可以手動為它設置回適當?shù)闹?。但是,以這種方式重設 constructor 屬性回導致它的 [[Enumerable]] 特性被設置為 true。默認情況下,原生的 constructor 屬性是不可枚舉的。

function Person(){}

Person.prototype = {
  constructor: Person,
  name: 'Nicholas',
  age: 29,
  job: 'Software Engineer',
  sayName: function (){
    console.log(this.name);
  }
}

重設構(gòu)造函數(shù),只適用于 ECMAScript5 兼容的瀏覽器。

Object.defineProperty(Person, 'constructor', {
  enumerable: false,
  value: Person
})

原型的動態(tài)性

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

實例與原型之間的關(guān)系是松散的,

function Person(){}

const friend = new Person();

Person.prototype = {
  constructor: Person,
  name: 'Nicholas',
  age: 29,
  job: 'Software Engineer',
  sayName: function (){
    console.log(this.name);
  }
};

friend.sayName();
// error

重寫原型對象切斷了現(xiàn)有原型與任何之前已經(jīng)存在的對象實例之間的聯(lián)系,它們引用的仍然是最初的原型。

原型對象的原型

原型模式的重要性不僅體現(xiàn)在創(chuàng)建自定義類型方面,就連所有原生的引用類型,都是采用這種模式創(chuàng)建的。所有原生引用類型(Object、Array、String 等等)都在其構(gòu)造函數(shù)的原型上定義了方法。

通過原生對象的原型,不僅可以取得所有默認方法的引用,而且也可以定義新方法??梢韵裥薷淖远x對象的原型一樣修改原生對象的原型,因此可以隨時添加方法。

盡管可以這樣做,但我們不推薦在產(chǎn)品化的程序中修改原生對象的原型。如果因某個實現(xiàn)中缺少某個方法,就在原生對象的原型中添加這個方法,那么當在另一個支持該方法的實現(xiàn)中運行代碼時,就可能會導致命名沖突。而且,這樣做也可能會意外地重寫原生方法。

原型對象的問題

原型模式省略了為構(gòu)造函數(shù)傳遞初始參數(shù)的環(huán)節(jié),結(jié)果所有實例在默認情況下都將取得相同的屬性值。

原型中的所有屬性是被很多實例共享的,這種共享對于函數(shù)非常合適。對于那些包含基本值的屬性倒也說得過去,畢竟,通過在實例上添加一個同名屬性,可以隱藏原型中的對應屬性。然而,對于包含引用類型值的屬性來說,問題就比較突出了。文章來源地址http://www.zghlxwxcb.cn/news/detail-840628.html

function Person(){}

Person.prototype = {
  name: 'Nicholas',
  age: 29,
  job: 'Software Engineer',
  friends: ['Shelby', 'Court'],
  sayName: function (){
    console.log(this.name);
  }
}

const person1 = new Person();
const person2 = new Person();

person1.friends.push('Van');

console.log(person1.friends);
// 'Shelby,Court,Van'
console.log(person2.friends);
// 'Shelby,COurt,Van'
console.log(person1.friends == person2.friends);
// true

到了這里,關(guān)于【編程向?qū)А縅avaScript-創(chuàng)建對象一期講解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關(guān)文章

  • JavaScript系列從入門到精通系列第二十篇:使用工廠方法創(chuàng)建JavaScript對象,JavaScript構(gòu)造函數(shù)詳解,JavaScript類概念的介紹

    JavaScript系列從入門到精通系列第二十篇:使用工廠方法創(chuàng)建JavaScript對象,JavaScript構(gòu)造函數(shù)詳解,JavaScript類概念的介紹

    文章目錄 一:使用工廠方法創(chuàng)建對象 1:原始寫法 2:工廠方式 3:結(jié)果驗證? 二:構(gòu)造函數(shù) 1:什么是構(gòu)造函數(shù) 2:構(gòu)造函數(shù)和普通函數(shù)的區(qū)別 3:構(gòu)造函數(shù)的執(zhí)行流程 三:類 1:什么是類 2:如何檢查一個對象是否是個類的實例 3:Object的地位 四:構(gòu)造函數(shù)修改 1:重大問題

    2024年02月08日
    瀏覽(26)
  • JavaScript 手寫代碼 第一期

    JavaScript 手寫代碼 第一期

    我們在日常開發(fā)過程中,往往都是取出來直接用,從來不思考代碼的底層實現(xiàn)邏輯,但當我開始研究一些底層的東西的時候,才開始理解了JavaScript每個方法和函數(shù)的底層實現(xiàn)思路,我認為這可以很好的提高我們的代碼水平和邏輯思維。 2.1.1 基本使用 定義 : 靜態(tài)方法以一個現(xiàn)

    2024年02月10日
    瀏覽(22)
  • 【編程向?qū)А看a管理-Git四期期講解

    Git 最強大的就是其分支功能,但是如何分支才能更有效的提高開發(fā)效率,減少因為代碼合并帶來的問題,需要一個分支模型來規(guī)范,其實在 Git Flow 出現(xiàn)之前,已經(jīng)有分支模型理論流程,當時是根據(jù)此理論,手動的按照規(guī)范操作分支,Git Flow 出現(xiàn)之后,將一部分操作流程簡化

    2024年04月10日
    瀏覽(12)
  • leetcode — JavaScript專題(五):計數(shù)器 II、只允許一次函數(shù)調(diào)用、 創(chuàng)建 Hello World 函數(shù)、將對象數(shù)組轉(zhuǎn)換為矩陣、節(jié)流、分塊數(shù)組

    專欄聲明:只求用最簡單的,容易理解的方法通過,不求優(yōu)化,不喜勿噴 題面 請你寫一個函數(shù) createCounter. 這個函數(shù)接收一個初始的整數(shù)值 init 并返回一個包含三個函數(shù)的對象。 這三個函數(shù)是: increment() 將當前值加 1 并返回。 decrement() 將當前值減 1 并返回。 reset() 將當前值

    2024年02月03日
    瀏覽(40)
  • 【JavaScript】講解JavaScript的基礎知識并且配有案例講解

    【JavaScript】講解JavaScript的基礎知識并且配有案例講解

    ??專欄【?前端易錯合集】 ??喜歡的詩句:更喜岷山千里雪 三軍過后盡開顏。 ??音樂分享【如愿】 大一同學小吉,歡迎并且感謝大家指出我的問題?? 目錄 ? ??JavaScript嵌入網(wǎng)頁的方式 ??alert(\\\"這是一個JavaScript例子\\\"); ????(或者window.alert()) ???document.write(\\\"這是一個Jav

    2024年02月08日
    瀏覽(50)
  • 【JavaScript速成之路】JavaScript內(nèi)置對象--字符串對象

    【JavaScript速成之路】JavaScript內(nèi)置對象--字符串對象

    ??個人主頁:「小楊」的csdn博客 ??系列專欄:【JavaScript速成之路】 ??希望大家多多支持??一起進步呀! ??前言:小楊在上一篇帶著大家一起學習了JavaScript中的內(nèi)置的數(shù)組對象,想必大家對JavaScript的內(nèi)置的數(shù)組對象已經(jīng)有所了解了,那么今天我們將繼續(xù)帶著大家學習一

    2023年04月10日
    瀏覽(28)
  • 【JavaScript】5.JavaScript內(nèi)置對象

    【JavaScript】5.JavaScript內(nèi)置對象

    JavaScript 中的對象分為3種 自定義對象 內(nèi)置對象 瀏覽器對象 前面兩種對象是JS 基礎 內(nèi)容,屬于 ECMAScript; 第三個瀏覽器對象屬于JS 獨有的 內(nèi)置對象就是指 JS 語言自帶的一些對象,這些對象供開發(fā)者使用,并提供了一些常用的或是最基本而必要的功能(屬性和方法) 內(nèi)置對

    2023年04月20日
    瀏覽(35)
  • javascript中的this與函數(shù)講解

    javascript中的this與函數(shù)講解

    前言 javascript中沒有塊級作用域(es6以前),javascript中作用域分為函數(shù)作用域和全局作用域。并且,大家可以認為全局作用域其實就是Window函數(shù)的函數(shù)作用域,我們編寫的js代碼,都存放在Window函數(shù)內(nèi)(這是個假設),也就是說javascript中只有函數(shù)作用域(前面假設做前提下)

    2024年02月06日
    瀏覽(17)
  • javascript基礎十:說說你對Javascript中this對象的理解

    javascript基礎十:說說你對Javascript中this對象的理解

    一、定義 函數(shù)的 this 在 JavaScript 中的表現(xiàn)略有不同,此外,在嚴格模式和非嚴格模式之間也會有一些差別 在絕大多數(shù)情況下,函數(shù)的調(diào)用方式?jīng)Q定了 this 的值(運行時綁定) this 是函數(shù)運行時自動生成的一個內(nèi)部對象,只能在函數(shù)內(nèi)部使用,總指向調(diào)用它的對

    2024年02月06日
    瀏覽(26)
  • 4 JavaScript數(shù)組和對象

    4 JavaScript數(shù)組和對象

    4 數(shù)組和對象 在JS中創(chuàng)建數(shù)組非常簡單. 直接[ ]即可. 也可以用正規(guī)軍的new Array(). 不過效果都是一樣的. 數(shù)組的常用操作: 在JS中創(chuàng)建一個對象非常容易. 和python中的字典幾乎一樣{ }: 使用對象 從上述內(nèi)容中幾乎可以看到. JS對象的使用幾乎是沒有門檻的. 十分靈活 代碼的效果圖如

    2024年02月12日
    瀏覽(20)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包