一般會問的問題:
- 創建對象有幾種方法
- 原型、構造函數、實例、原型鏈
- instanceof 的原理
- new 運算符
創建對象有幾種方法
原型關系
- 每個class(class 實際是函數,是語法糖)都有顯示原型 prototype
- 每個實例都有隱式原型 __proto__
- 實例的 __proto__ 指向對應class 的 prototype
基於原型的執行規則
- 獲取屬性 xialuo.name 或執行方法 xialuo.sayhi() 時
- 先在自身屬性和方法尋找
- 如果找不到則自動去 __proto__ 中尋找
原型、構造函數、實例、原型鏈
- 原型鏈:從一個實例對象往上找構造這個實例的相關聯的對象,然后這個關聯的對象再往上找它又有創造它的上一級的原型對象,以此類推,一直到 Object.prototype 原型對象終止,這個鏈條就斷了,也就是說 Object.prototype 是整個原型鏈的頂端。通過什么往上找?就是通過 prototype 和 __proto__.
- 原型:構造函數都有一個 prototype 屬性,這是在聲明一個函數時js 自動增加的,這個 prototype 指的就是原型對象。原型對象怎么區分被哪個構造函數引用?就是通過 constructor(構造器),原型對象中會有一個構造器,這個構造器會默認聲明的那個函數。
- 構造函數:任何一個函數只要被 new 去操作(使用)就是構造函數,構造函數也是函數
- 實例:只要是對象就是一個實例
- 構造函數可以使用new 生成實例
通過原型鏈的方式找到原型對象,原型對象的方法是被不同的實例所共有的,這就是原型鏈的一個工作原理
1、構造函數(函數)才有propotype 的,對象沒有 propotype,
2、只有實例對象有 __proto__的,函數既是函數又是對象
原型鏈
- 如果實例中有自身屬性則直接使用自身的屬性(如圖中 xialuo),如果沒有則會再自身的隱式原型鏈中去找,一直找到最頂級 Object 為止,如果都找不到,則最后返回的null
- 每個構造函數都有一個顯示原型prototype (如 Student, People),且每個顯示原型都會對應有一個隱式原型__proto__,而他的隱式原型的父級又有個顯示原型,他們都是一級級往上找的,然后一直找到樹形結構的第一層(Object)為終點
- instanceof 是為判斷此實例或構造函數是否是父級繼承的,如(xialuo instanceof People // true, xialuo instanceof Array // false)
instanceof 原理:
實例對象的 __proto__ 和構造函數本身沒有什么關聯,它關聯的是構造函數 prototype 下面的一個屬性即 prototype 所引用的原型對象
是判斷 實例對象.__proto__ 和 構造函數.prototype是不是一個引用(即引用同一個地址)
new 運算符
new 構造函數的原理:
生成一個空對象(Object.create)
將空對象的__proto__指向構造函數的prototype var o = Object.create(func.prototype)
執行構造函數,this 上下文指向空對象 var k = func.call(o)
若構造函數返回的是對象,那么這個對象將取代原來的空對象
if(typeof k === 'object') {
return k
} else {
return o
}
題目
如何准確判斷一個變量是不是數組?
答案:用 instanceof, 如 a instanceof Array
手寫一個簡易的 jQuery,考慮插件和擴展性
1 class jQuery { 2 constructor(selector) { 3 const result = document.querySelectorAll(selector) 4 const length = result.length 5 for(let i = 0; i < length; i++) { 6 this[i] = result[i] 7 } 8 this.length = length 9 this.selector = selector 10 } 11 get(index) { 12 return this[index] 13 } 14 each(fn) { 15 for(let i = 0; i < this.length; i++) { 16 const elem = this[i] 17 fn(elem) 18 } 19 } 20 21 on(type, fn) { 22 return this.each(elem => { 23 elem.addEventlistener(type, fn, false) 24 }) 25 } 26 } 27 28 jQuery.propotype.dialog = function(info) { 29 alert(info) 30 } 31 32 class myJQuery extends jQuery { 33 constructor(selector) { 34 supper(selector) 35 } 36 addClass(className) { 37 } 38 style(data) { 39 } 40 }
class的原型本質,怎么理解?
答案:
- 上面原型和原型鏈的圖示
- 屬性和方法的執行規則