JavaScript --- [學習筆記] 原型模式

說明

  • 接JavaScript — > [學習筆記]觀察者模式 & 理解對象 & 工廠模式 & 構造函數模式
  • 上一篇構造函數模式創建的實例,不同實例的同一個方法是不相等的,為了解決這個問題.出現了原型模式

1. 原型模式

  • 具體做法是,不在構造函數中定義對象實例的信息,而是將這些信息直接添加到原型對象
function Person(){}
Person.prototype.name ="Nicholas";
Person.prototype.age =29;
Person.prototype.job ="Software Engineer";
Person.prototype.sayName = function () {alert(this.name);
};
var person1 = new Person();
person1.sayName();    // "Nicholas"var person2 = new Person();
person2.sayName();    // "Nicholas"console.log(person1.sayName == person2.sayName);    // true

1.1 理解原型對象

1.1.1 prototype屬性和constructor屬性

  • 創建一個函數(Person),就會根據一組規則創建一個prototype屬性(Person.prototype)
  • prototype上面還要一個constructor屬性(必帶技能),它(Person.prototype.constructor)指向函數Person
  • prototype屬性上的所有屬性和方法會被所有使用new操作符生產的實例(person1, person2)共享
  • 實例person1、person2通過new Person得到,會有一個[[Prototype]]的指針(在瀏覽器中通過__proto__訪問),它指向Person.prototype

1.1.2 讀取某個屬性的順序

  • 讀取屬性的模擬函數如下:
// obj是某個對象, attr是該對象的屬性
const getVal = (obj, attr) =>{// 如果對象中存在該屬性則返回if(obj[attr]) {return obj[attr]} else if (obj.constructor === Object) {// 是Objectreturn undefined} else{// 不是Object,檢查其constructor指向的函數if(obj.constructor[attr]){return obj.constructor[attr]} else {// constructor指向的函數中不存在,順著 __proto__ 屬性找下去.getVal(obj.__proto__, attr);}}
}

說明:

  1. 所有通過function聲明的函數,都繼承自Function
  2. Function繼承自Object

1.1.3 說說

通過上面的原型找屬性的順序,可以知道:

  1. 當使用new Person生成實例(person1)的時候,person1會有一個指向Person.prototype的指針__proto__
  2. 當訪問person1的屬性或方法的時候,先從實例開始尋找,若找到了則返回,否則會順著__proto__向上尋找

1.2 區分一個屬性是否來自原型

需要明白下面2點:

  1. 使用in操作符會返回所有對象上的屬性或者方法
  2. 使用hasOwnProperty可以確定一個屬性是否來自實例對象
// 判斷一個熟悉是否來自原型
const fromPrototype = (obj, attr) {return !obj.hasOwnprototype && (attr in obj);
}

1.3 Object.defineProperty

  • Object.defineProperty: 可以給一個對象添加屬性,并對屬性進行描述
  • 使用如下:
Object.defineProperty(Person.prototype, "constructor", {enumerable: false,value: Person
})

1.3.1 數據屬性和訪問器屬性

  1. JS中的屬性類型分為: 數據屬性和訪問器屬性
  2. 數據屬性包括:
  • [[Configurabal]]: 是否能被delete刪除
  • [[Numerable]]: 是否能被for-in循環訪問屬性
  • [[Writeble]]: 是否可以被修改
  • [[Value]]: 屬性的值
  1. 訪問器屬性: Configurable、Numerable、Get(讀取時觸發) 、Set(修改時觸發)

1.3.2 Object.defineProperty的使用

  • 在使用對象字面量對函數的原型進行賦值的時候,會丟失原本的constructor屬性
  • 使用Object.defineProperty為它加上constructor屬性
function Person () {}
Person.prototype = {name: 'marron',age: 18
}
Object.defineProperty(Person.prototype, constructor, {numerable: false,value: Person
})
  1. constructor是不能被for-in循環訪問到的
  2. 在字面量中直接賦值,會被for-in循環訪問到

1.4 原型的動態性

  • 可以先創建實例后修改原型
function Person () {};
cosnt friend = new Person();
Person.prototype.sayHi =  () => { console.log('SayHi') };
friend.sayHi();
  • 將上述代碼修改為下面:
- Person.prototype.sayHi  = () => { console.log('SayHi') };
+ Person.prototype = {
+ 		sayHi: function () {
+ 			console.log('SayHi');
+ 		}
+ }
  • 此時在調用friend.sayHi會報錯: Uncaught TypeError: p1.sayHi is not a function, 原因如下:
  1. 使用new操作符時: 建立了一個指針 proto, 它指向 Person.prototype(這個是默認建立的),假設在空間A中,即此時 person1 先從自己的空間中取數據,若沒有則去 A中找
  2. 當對Person.prototype進行字面量賦值時, 它改變的是Person.prototype指針的指向,在上面的一系列操作實際是在空間B中.
  3. 當完成了Person.prototype的字面量賦值后,相當于給Person的原型對象新開辟了一個空間B.而此時person1的__proto__還是指向A.故訪問不到B

注:重寫原型對象切斷了現有原型與任何之前已經存在的對象實例之間的聯系.

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/250384.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/250384.shtml
英文地址,請注明出處:http://en.pswp.cn/news/250384.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

網絡協議各層概述

網絡協議概述 OSI是一個開放性的通信系統互連參考模型,他是一個定義得非常好的協議規范。OSI模型有7層結構,每層都可以有幾個子層。 OSI的7層從上到下分別是 7 應用層 6 表示層 5 會話層 4 傳輸層 3 網絡層 2 數據鏈路層 1 物理層; 其中高層&…

A start job is running for Raise network interface(5min 13s )問題解決方法

命令:sudo vim /etc/systemd/system/network-online.target.wants/networking.service將里面的TimeoutStartSec5min 修改為TimeoutStartSec2sec 然后重啟系統,就可以生效了,開機速度很快 轉載于:https://www.cnblogs.com/sea-stream/p/98615…

javascript --- 實現對象的深拷貝

淺拷貝和深拷貝 淺拷貝: 只拷貝一層.當對象是復雜數據類型(Object、 Array)時,只拷貝引用深拷貝: 多層拷貝.復雜數據類型,會重新分配內存空間. 實現淺拷貝的2種方法 使用for ... in 實現 var obj {name: marron,age: 18,msg: {sex: "1" } } var o {}; for(let …

Qt與FFmpeg聯合開發指南(二)——解碼(2):封裝和界面設計

與解碼相關的主要代碼在上一篇博客中已經做了介紹,本篇我們會先討論一下如何控制解碼速度再提供一個我個人的封裝思路。最后回歸到界面設計環節重點看一下如何保證播放器界面在縮放和拖動的過程中保證視頻畫面的寬高比例。 一、解碼速度 播放器播放媒體文件的時候播…

Bzoj1051 受歡迎的牛

每一頭牛的愿望就是變成一頭最受歡迎的牛。現在有 N 頭牛,給你 M 對整數 (A,B),表示牛 A 認為牛 B 受歡迎。這種關系是具有傳遞性的,如果 A 認為 B 受歡迎,B 認為 C 受歡迎,那么牛 A 也認為牛 C 受歡迎。你的任務是求出…

node --- 模塊加載機制

1. Node.js中模塊加載機制 1.1 模塊查找規則-當模塊擁有路徑但沒有后綴時 require(./find.js); require(./find);require方法根據模塊路徑查找模塊,如果是完整路徑,直接進入模塊如果模塊后綴省略,先找同名JS文件再找同名JS文件夾 require(./find); // 以上會先找到命令行目錄…

51Nod 蜥蜴和地下室(搜索)

哈利喜歡玩角色扮演的電腦游戲《蜥蜴和地下室》。此時,他正在扮演一個魔術師。在最后一關,他必須和一排的弓箭手戰斗。他唯一能消滅他們的辦法是一個火球咒語。如果哈利用他的火球咒語攻擊第i個弓箭手(他們從左到右標記)&#xff…

多線程——實現Runnable接口實現一個多線程

實現Runnable接口實現一個多線程 Runnable接口源碼: package java.lang; //Runnable接口源碼只有一個run方法 public interface Runnable {public abstract void run(); } 實現Runnable的兩個多線程類: public class RunnableThread1 implements Runnabl…

javascript --- 文件上傳即時預覽 閉包實現多圖片即時預覽

使用javascript原生功能實現,點擊上傳文件,然后再網頁上顯示出來 1. 初級顯示 1.1 準備一個input標簽和一個img標簽 <input typefile id"file"> <img id"preview" src"">1.2 js代碼如下 // 將上傳的圖片顯示到頁面上function sho…

第一次作業:深入Linux源碼分析進程模型

一.進程的概念 第一&#xff0c;進程是一個實體。每一個進程都有它自己的地址空間&#xff0c;一般情況下&#xff0c;包括文本區域&#xff08;text region&#xff09;、數據區域&#xff08;data region&#xff09;和堆棧&#xff08;stack region&#xff09;。文本區域存…

關于模型驗證那點事兒

今天應笑笑老師之問&#xff0c;做了一個模型驗證的例子&#xff0c;發現之前對這個東西的理解太片面&#xff0c;重新整理了一下思路 字段驗證優先級高于類驗證 什么是類驗證呢&#xff1f;就是兩個字段組合的驗證&#xff0c;比如你Admin不允許修改密碼&#xff0c;你修改密碼…

mongoose --- createUser

說明 源代碼記錄、遺忘回顧mongoDB默認不需要使用賬號密碼即可訪問數據庫.下面是給mongoDB添加超級管理員和普通用戶的方法 以系統管理員的方式運行powershell連接數據庫 mongo查看數據庫: show dbs切換到admin數據庫: use admin創建超級管理員賬戶: db.createUser({user: roo…

Win10安裝MySQL5.7.22 解壓縮版(手動配置)方法

1.下載地址&#xff1a;https://dev.mysql.com/downloads/mysql/5.7.html#downloads 直接點擊下載項 下載后&#xff1a; 2.可以把解壓的內容隨便放到一個目錄&#xff0c;我的是如下目錄&#xff08;放到C盤的話&#xff0c;可能在修改ini文件時涉及權限問題&#xff0c;之后我…

Elemant-UI日期范圍的表單驗證

Form 組件提供了表單驗證的功能&#xff0c;只需要通過 rules 屬性傳入約定的驗證規則&#xff0c;并將 Form-Item 的 prop 屬性設置為需校驗的字段名即可。但是官網的示例只有普通日期類型的驗證&#xff0c;沒有時間范圍的驗證。 一開始&#xff0c;我認為時間時間范圍的是一…

node --- [express項目] 開發環境下使用morgan控制臺輸出訪問信息

說明 源代碼記錄、遺忘回顧 process.env node中提供了一個process.env接口用于訪問計算機中的系統環境變量. 可以利用以上屬性來區分當前的環境是開發環境還是生產環境,代碼如下: if (process.env.NODE_ENV development) {console.log(當前環境是開發環境) } else {consol…

Dynamics CRM 訪問團隊的使用

訪問團隊和負責人團隊的區別是&#xff1a;負責人團隊可以擁有記錄&#xff0c;訪問團隊不能擁有記錄也不能加入解決方案中。 訪問團隊用法1&#xff1a;可以將不同組織的人員加入到訪問組實現數據的更新、刪除、共享 訪問團隊用法2&#xff1a;訪問團隊模板的使用 步驟一&…

業務邏輯

快捷支付接口規范 問題背景 持卡人身份驗證持卡人在發卡銀行提供的身份驗證服務器進行驗證&#xff0c;將結果告知商戶資金清算資金清算在身份驗證通過后進行即時清算&#xff0c;也可能是通過專用資金清算網絡進行傳統方法弊端 持卡人需要訪問很多網站才能完成一次完整支付 &a…

node --- [express] cookie/session 機制與 中間件的使用(路由守衛)

說明 源代碼記憶、遺忘回顧使用 cookie/session 機制,讓 客戶端/服務器 的訪問變得有狀態 cookie 與 session 由于 HTTP 協議的無狀態性,當一次連接斷開后. 服務器并不會記錄用戶是否登錄. 因此需要引入 cookie/session 機制 cookie cookie: 瀏覽器在電腦硬盤中開辟的一塊空…

kprobe原理解析

參考 http://www.cnblogs.com/honpey/p/4575928.html kprobe是linux內核的一個重要特性&#xff0c;是一個輕量級的內核調試工具&#xff0c;同時它又是其他一些更高級的內核調試工具&#xff08;比如perf和systemtap&#xff09;的“基礎設施”&#xff0c;4.0版本的內核中&a…

02 數據類型

轉載于:https://www.cnblogs.com/theoup/p/9875293.html