猛然間發現都須要在牛客網上視頻面試了。html
好氣人呀,一週內面試筆者竟然再原型鏈問題上被連續絆倒兩次,而後被斷定爲 JS 基礎薄弱。真的好氣人呀,因此筆者研究了一下午的原型鏈,打算以後不再會被這個絆倒,其遇到的題目和你們分享。面試
Function.prototype.a = () => { console.log(1); } Object.prototype.b = () => { console.log(2); } function A() {} const a = new A(); a.a(); a.b(); A.a(); A.b();
真的再不少地方出現了,我一搜才發現其餘朋友在 JD 的面試上也遇到過。我遇到的當晚也寫了一份解答思路:面試:Function.prototype.a 請給出下列函數的執行輸出算法
對於 new 出來的對象 a 的屬性,原型鏈查找的順序應該是promise
1. a 自身 2. `a.__proto__` 至關於 A.prototype 3. `A.prototype.__proto__` 至關於 Object.prototype 4. `Object.prototype.__proto__` 這個爲 null,原型鏈查找到頭。
對於 function 定義的函數 A 的屬性,原型鏈查找順序應該是閉包
1. A 自身 2. `A.__proto__` 至關於 Function.prototype 3. `Function.prototype.__proto__` 等於 Object.prototype 4. `Object.prototype.__proto__` 這個爲 null,原型鏈查找到頭。
function A() { } A.prototype.n = 0; A.prototype.add = function () { this.n += 1; } a = new A(); b = new A(); a.add(); console.log(b.add())
這是在快手後的網易面試,自從有了題1,我對這一套就開始疑神疑鬼的,想的複雜了。框架
構造函數 new 出來的對象,其方法 this 都指向他的實例。因此調用完 add 方法,遇到 this.n += 1;
,這個 this 指向的又是實例對象。因此咱們的 a 對象 和 b 對象都有獨屬於本身的 n。函數
function Person(name, age) { this.name = name; this.age = age; this.eat = function() { console.log(age + "歲的" + name + "在吃飯。"); } } Person.run = function () {} Person.prototype.walk = function () {} let p1 = new Person("jsliang", 24); let p2 = new Person("jsliang", 24); console.log(p1.eat === p2.eat); // false console.log(p1.run === p2.run); // true console.log(p1.walk === p2.walk); // true
new 操做符使得構造函數內的 eat 函數(對象),是在堆中新開一份空間放置,因此兩個實例對象它天然不共享。this
而原型上兩個實例對象天然都是同一份,walk 方法相同。prototype
須要注意的是 p1.run 和 p2.run 都是 undefined。由於 run 方法只是做爲 Person 本身的靜態屬性,p1 和以後的原型鏈上是找不到的。3d
function A() { this.test = 1 } var a = new A(); a.test a = new A; a.test a = A() a.test A.test
提示讀者們,的是 new A 等價與 new A(),MDN上這麼說
使用指定的參數調用構造函數 Foo,並將 this 綁定到新建立的對象。new Foo 等同於 new Foo(),也就是沒有指定參數列表,Foo 不帶任何參數調用的狀況。
而 a = A()
只是把 A 做爲普通函數執行了,這個普通函數內部並沒有 return 出什麼來,因此 a 只是 undefined,a.test 就會報錯。
至於 A.test
, A 只是個函數定義,A 自己沒獲得執行,天然不會有什麼 test 屬性,只能往 Function.prototype 上找,天然仍是找不到了。
要是 Java 後三個都得報語法錯誤,我開始沒那麼喜歡 JS 了。
function A() {} function B(a) { this.a = a; } function C(a) { if (a) { this.a = a; } } A.prototype.a = 1; B.prototype.a = 1; C.prototype.a = 1; console.log(new A().a); // 1 console.log(new B().a); // undefined console.log(new C(2).a); // 2
console.log(new B().a); // undefined
,你須要知道此時 B 它自身屬性裏已經有了一個 a 屬性了
問 foo1 上究竟都掛着什麼屬性
function foo() { this.some = '222' let ccc = 'ccc' foo.obkoro1 = 'obkoro1' foo.prototype.a = 'aaa' } foo.koro = '扣肉' foo.prototype.test = 'test' let foo1 = new foo() foo.prototype.test = 'test2'
foo1 上掛着屬性 some,其原型鏈上掛着 test 和 a,至於 foo.obkoro1 只是靜態屬性不影響 foo1,ccc 更是閉包裏的變量更不要緊。
__proto__
非標準,有什麼能替代它獲取原型鏈?去年開始出門面試,那時候被卡的是框架源碼和實現細節;以後就被問各類基建系統的實現;等年初出門面幾家,發現全都作算法題了;等我花了一陣子把什麼鏈表堆棧的 leetcode 題刷過,發現最近面的沒有一個問算法題,卻都在問這種 「JS 基礎題」。面試真的是一門玄學,怎麼準備都不夠。
哦,對了,還有 promise 微任務組合起來的輸出的問題,也坑了我好屢次,留給後面的篇幅吧。真的好討厭這樣的問題啊!