摘要:寫在最前構造函數和原型模式的使用場景很廣泛,但因為對概念的混淆不清導致無法熟練掌握。換句話說,不必在構造函數中定義對象實例的信息,而是可以將這些信息直接添加到原型對象中,比如下面的方法。
寫在最前:構造函數和原型模式的使用場景很廣泛,但因為對概念的混淆不清導致無法熟練掌握。切圖帶你從代碼和流程圖一步步攻克,純干貨,建議收藏詳看,原型模式理解圖非常重要,務必多看幾遍!
前往查看demo源碼
js基礎(一):判斷類型
構造函數的首字母必須大寫,用來區分于普通函數(駝峰命名),此為約定俗成
構造函數內部使用的this對象,來指向即將要生成的實例對象,而普通函數中的this指向調用函數的對象(沒有對象時默認為window)
構造函數默認return this,但也可以用return語句,返回值會根據return值的類型而有所不同。普通函數可使用return返回值
構造函數使用New來生成實例對象進行調用,普通函數直接調用
// 構造函數 function Person(name, age) { this.name = name this.age = age this.introduction = function() { console.log(`my name is ${this.name}, I"m ${this.age} years old`) } //return this //構造函數默認有這句 } var p = new Person("qietuniu", 18) // this=Person p.introduction() // 普通函數 function person(name, age) { this.name = name this.age = age this.introduction = function() { console.log(`my name is ${this.name}, I"m ${this.age} years old`) } return `直接返回:我的名字 ${this.name}, 我 ${this.age} 歲` } console.log(person("qietuniu", 18)) //this=window window.introduction()
構造函數內的上下文this指向即將要生成的實例對象Person,普通函數內使用this,指向window時容易造成全局污染。該構造函數將陪著我們讀完這篇文章,之后的示例將在這基礎上演示!
隱藏的構造函數var a={}是var a=new Object()的語法糖
var a=[]是var a=new Array()的語法糖
function Person(){}是var Person=new Function()的語法糖
語法糖:更簡單表達一個操作的語法,能夠增加程序的可讀性,在性能上不會帶來損失的同時提高開發編碼的效率,從而減少程序代碼出錯的機會!instanceof
可使用instanceof判斷一個函數是否是一個變量的構造函數.
解析:instanceof的判斷邏輯是實例p的__proto__一層一層往上,能否對應到Person.prototype,同樣也能到Object.prototype.
查看instanceof具體使用>>
new一個對象的過程創建一個新對象
this指向這個新對象
執行代碼,即對this賦值
返回this
解析(以Person函數為例):原型模式 原型模式理解圖
1.創建一個新對象p
2.將構造函數Person()中的this指向新創建的對象p
3.p的_proto_(隱式原型)屬性指向Person函數的prototype(顯示原型),創建構造函數與原型以及對象的關系
4.調用對象,執行Person內屬性或方法
構造函數Fn的prototype(顯式原型)是原型對象
構造函數可通過new實例化一個實例
原型對象的constructor是構造函數Fn
Person.prototype.constructor = Person
實例的構造函數屬性(constructor)指向構造函數
p的__proto__.constructor = Person
實例的__proto__(隱式原型)是原型對象
p的__proto__ =Person.prototype
Fn.prototype是對象,它的__proto__是object的prototype
Person.prototype的__proto__ = Object.prototype
Object的prototype的__proto__為null
Object.prototype的__proto__ = null
Person.prototype的__proto__的__proto__ = null
熟記該圖,萬變不離其宗原型的五大原則(學習原型鏈的基礎)
1. 所有的引用類型(數組、對象、函數),都具有對象特性,即可自由擴展屬性(null除外)
var obj = {} obj.a = 100 //自由擴展屬性 var arr = [] arr.a = 100 function fn() {} fn.a = 100
創建對象的三種方法
// 字面量 var o1 = { name: "o1" } var o2 = new Object({ name: "o2" }) // 構造函數 var M = function() { this.name = "o3" } var o3 = new M() // Object.create var O = { name: "o4" } var o4 = Object.create(O) console.log(o1) console.log(o2) console.log(o3) console.log(o4)
2. 所有的引用類型(數組、對象、函數),都有一個__proto__屬性(隱式原型),屬性是一個普通的對象
//隱式原型 console.log(obj.__proto__) console.log(arr.__proto__) console.log(fn.__proto__)
3. 所有的函數,都有一個prototype屬性(顯式原型),屬性也是一個普通的對象
//顯式原型 console.log(fn.prototype)
4. 所有的引用類型(數組、對象、函數),_proto_屬性值指向它的構造函數的“prototype”的值
//_proto_屬性值指向它的構造函數的“prototype”的值 console.log(`arr.__proto__ === Array.prototype:${arr.__proto__ === Array.prototype}`) console.log(`obj.__proto__ === Object.prototype:${obj.__proto__ === Object.prototype}`) console.log(`fn.__proto__ === Function.prototype:${fn.__proto__ === Function.prototype}`)
5. 當試圖得到一個對象的某個屬性時,如果這個對象本身沒有這個屬性,那么會去它的__proto__(即它的構造函數的prototype)中尋找
Person.prototype.sayName = function() { console.log(`我的名字:${this.name}`) } p.introduction() p.sayName()
執行sayName時的時候,對象p本身沒有該方法,會去它的__proto__即它的構造函數的prototype中尋找(p.__proto__或者Person.prototype),于是找到sayName.原型對象
什么是原型對象
Person這個構造函數的顯式原型是一個對象,簡稱原型對象。Person.prototype就是原型對象。
每個構造函數都有一個原型對象,原型對象都包含一個指向構造函數的指針,而實例都包含一個指向原型對象的內部指針,即原型對象(Person.prototype)是 構造函數(Person)的一個實例。
Person.prototype = p.__proto__
原型對象的優點
可以 讓所有對象實例共享它所包含的屬性和方法。換句話說,不必在構造函數中定義對象實例的信息,而是 可以將這些信息直接添加到原型對象中,比如下面的sayName方法。
Person.prototype.sayName = function() { console.log(`我的名字:${this.name}`) }
如何查找對象自身的屬性
var item for (item in p) { // 高級瀏覽器已經在for in中屏蔽了來自原型的屬性 // 以下的判斷可保證程序的健壯性,hasOwnProperty方法會返回一個布爾值,指示對象自身屬性中是否具有指定的屬性 if (p.hasOwnProperty(item)) { // 輸出name和printName,沒有alerName console.log(item) } }原型鏈
ECMAScript 中描述了原型鏈的概念,并將原型鏈作為實現繼承的主要方法。其基本思想是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法。
p.toString()是如何調用的
執行toString方法時,p本身沒有該方法,p.__proto__也沒有,繼續往上p.__proto__.__proto__即Person.prototype.__proto__,Person.prototype就是普通對象,Person.prototype.__proto__ = Object.prototype,Object中存在toString方法。
原型鏈圖
每個構造函數都有一個原型對象,原型對象都包含一個指向構造函數的指針,而實例都包含一個指向原型。對象的內部指針這么一層一層的查找就是原型鏈查找,如此層層遞進,就構成了實 例與原型的鏈條,這種鏈式結構叫做“原型鏈“。
使用場景 jquery中原型的使用jQuery.fn.init.prototype = jQuery.fn,將原型方法為什么放在jQuery.fn中,是因為要擴展插件如下面的printQT 方法, 只有$會暴露在window全局變量(太多會造成污染),將插件擴展統一到jQuery.fn.xxx這一個接口方便使用。
var jQuery = function() { return new jQuery.fn.init(); } jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function() { this.jquery = "1.9.1"; return this; } } jQuery.fn.init.prototype = jQuery.fn; jQuery.fn.printQT = function() { console.log("切圖") return this; } window.jQuery = window.$ = jQuery; console.log(jQuery().printQT())其他
除了jquery中的運用,在vue中使用諸如echarts的插件時,我們會使用Vue.prototype.$echarts = echarts,將echarts引入到全局使用,同樣自定義方法變量也可以如此使用。
尊重原創,如需轉載請注明出處!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/103175.html
摘要:原型鏈和對象的原型是對象實例和它的構造函數之間建立的鏈接,它的值是構造函數的。對象的原型根據上文提到的構造調用函數的時候會創建一個新對象,自動將的原型指向構造函數的對象。 showImg(https://segmentfault.com/img/remote/1460000020185197); JS的原型、原型鏈一直是比較難理解的內容,不少初學者甚至有一定經驗的老鳥都不一定能完全說清...
摘要:固有對象由標準規定,隨著運行時創建而自動創建的對象實例。普通對象由語法構造器或者關鍵字定義類創建的對象,它能夠被原型繼承。 筆記說明 重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄,每天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點筆記以及感悟,完整的可以加入winter的專欄學習【原文有winter的語音】,如有侵權請聯系我,郵箱:ka...
摘要:固有對象由標準規定,隨著運行時創建而自動創建的對象實例。普通對象由語法構造器或者關鍵字定義類創建的對象,它能夠被原型繼承。 筆記說明 重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄,每天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點筆記以及感悟,完整的可以加入winter的專欄學習【原文有winter的語音】,如有侵權請聯系我,郵箱:ka...
閱讀 1357·2021-11-24 09:39
閱讀 1346·2021-11-04 16:12
閱讀 2686·2021-09-24 09:47
閱讀 3337·2021-09-01 10:50
閱讀 1477·2019-08-30 15:55
閱讀 1423·2019-08-30 15:43
閱讀 642·2019-08-30 11:08
閱讀 3578·2019-08-23 18:33