鍍金池/ 問答/HTML/ JS中一切函數(shù)都是Function構(gòu)造函數(shù)創(chuàng)造的嗎?js原型、原型鏈的問題

JS中一切函數(shù)都是Function構(gòu)造函數(shù)創(chuàng)造的嗎?js原型、原型鏈的問題

我知道一般情況下函數(shù)都是Function的實(shí)例,例如:由function關(guān)鍵字定義的函數(shù),一些內(nèi)置函數(shù),Array、Number、StringObject、Function等等。還知道每一個(gè)函數(shù)都有一個(gè)prototype屬性,一般情況下,fn.prototype都是對(duì)象,但有個(gè)特例Function.prototype

var fn=function () {
    console.log('hello')
}
fn instanceof Function  //true  
Array instanceof Function  //true  
Object instanceof Function  //true
Function instanceof Function   //true 

typeof fn.prototype //"object"
typeof Array.prototype //"object"
typeof Object.prototype //"object"

但是typeof Function.prototype // "function"
既然是函數(shù),這個(gè)函數(shù)也是Function創(chuàng)造的嗎?

Function.prototype instanceof Function //false

Function.prototype這個(gè)函數(shù)為啥沒有prototype屬性?不是每個(gè)函數(shù)都有嗎?
在chrome控制臺(tái)打印Function.prototype是一個(gè)匿名函數(shù),想知道這個(gè)匿名函數(shù)是怎么來的?

回答
編輯回答
艷骨

Function.prototype 本身也是個(gè)函數(shù)對(duì)象,這是為了兼容 ES5。也估計(jì)是讓人引起誤解的源頭。但兩者還是不同的,這是個(gè)特殊的函數(shù)對(duì)象,它忽略參數(shù)總是返回 undefined,且沒有 [[Construct]] 內(nèi)部方法。

完整的說明 https://blog.crimx.com/2017/0...

2017年3月12日 20:34
編輯回答
冷咖啡

其實(shí)很容易理解,使用Function是這樣的

let f = new Funtion('x', 'return x')

那么再看下面的代碼

class _Function {
  constructor (param, expression) {
    this.param = param
    this.expression = expression
  }
}

let _f = new _Function('x', 'return x')

console.log(_Function.prototype) // _Function {}
console.log(_Function.prototype.prototype) // undefined
console.log(_Function.prototype.__proto__) // {}

console.log(Function.prototype) // [Function]
console.log(Function.prototype.prototype) // undefined
console.log(Function.prototype.__proto__) // {}
2018年9月7日 22:35
編輯回答
柒喵

其實(shí),所有的對(duì)象的根不是 Object,而是 Object.prototype, 所有的函數(shù)的根不是 Function,而是 Function.prototype, 當(dāng)然 Function.prototype 的原型鏈上級(jí)還有 Object.prototype,所以才有 function 也是 Object 的表現(xiàn)。

所有函數(shù)都是 Function 的示例, 這句話沒有錯(cuò),但是我們通過這個(gè)標(biāo)識(shí)符拿到的,只是 Function 的構(gòu)造器,而造實(shí)例用的 “模子” 其實(shí)是 Function.prototype, 所以謂之原型也。我是這么理解的,所有的 function 都是 Function 用 Function.prototype 構(gòu)造出來的,F(xiàn)unction 本身是一個(gè)構(gòu)造器函數(shù),所以 Function 也是用 Function.prototype 構(gòu)造出來的。

instanceof 操作符的本質(zhì)其實(shí)是檢查原型鏈上是否有指定的原型,試著用函數(shù)實(shí)現(xiàn)一個(gè) instanceof :

function instanceOf(obj, Ctor) {
    var proto = Object.getPrototypeOf(obj); // 獲得原型,等價(jià)于非標(biāo)準(zhǔn)的 __proto__
    if(proto === null) return false; // 原型為null,到鏈的盡頭了
    else if(proto === Ctor.prototype) return true; // 匹配到目標(biāo)原型對(duì)象
    else return instanceOf(proto, Ctor); // 繼續(xù)探測(cè)原型本身是否是這個(gè)構(gòu)造器構(gòu)造的
}

instanceOf(Function, Function) // true,因?yàn)?Function.__proto__ === Function.prototype

從 JS 的視角看,在JS宿主(瀏覽器、NodeJS)創(chuàng)建世界之初,天地一片混沌(劃掉),JS的世界里沒有任何對(duì)象。第一個(gè)被捏出來的對(duì)象,是 Object.prototype,緊接著根據(jù) Object.prototype 為原型,宿主創(chuàng)建了 Function.prototype, Array.prototype 等一系列類型原型對(duì)象,這些 prototype 是構(gòu)造內(nèi)置對(duì)象的模子。接著這才開始用 Function.prototype 構(gòu)造出 Object、Function、Number、Array 和 Object.prototype.valueOf、Array.prototype.forEach 等一系列的 function 。

Function.prototype 才是第一個(gè)從 Object.prototype 下細(xì)分出來的函數(shù),和 Object.prototype/Array.prototype 一樣,它制定函數(shù)作為對(duì)象時(shí)長(zhǎng)什么樣,有哪些方法屬性。至于它本身,就是一個(gè)空函數(shù)而已,它也不是構(gòu)造器,不能用 new 來創(chuàng)造對(duì)象,它只是 new Function 的時(shí)候用來構(gòu)造實(shí)例的模子。

//function(){} 是 object 的原型層面解釋
Function.prototype instanceof Object // true
Function.prototype.__proto__ === Object.prototype // true

至于 typeof 對(duì) function 的區(qū)分,我也不大了解,可能對(duì)象在構(gòu)造之初就有一個(gè)內(nèi)部屬性追蹤其是否是一個(gè)函數(shù)吧,比如:

({__proto__:Function.prototype}) instanceof Function // true
typeof ({__proto__:Function.prototype}) // 然而 typeof 還是返回 object

({__proto__: Array.prototype}) instanceof Array // true
Array.isArray({__proto__: Array.prototype}) // Array.isArray 一下就認(rèn)出來這是一個(gè)假冒的array

所以 instanceof 操作符真的很單純,它只是檢查原型鏈而已。

其實(shí)令人困惑的是 Function/Object 這些引用本身即代表類型又代表類型的構(gòu)造器。

===========================

2017年5月18日 10:22