Node.js中Object与Function在ECMA 规范中的关系

4次阅读

共计 4667 个字符,预计需要花费 12 分钟才能阅读完成。

Why in JavaScript both “Object instanceof Function” and “Function instanceof Object” return true?
一、ECMA5.1 规范中 instanceof
/*
how instanceof is defined by ECMA 5.1 Specification:

The production RelationalExpression: RelationalExpression instanceof ShiftExpression is evaluated as follows:

Let lref be the result of evaluating RelationalExpression.
Let lval be GetValue(lref).
Let rref be the result of evaluating ShiftExpression.
Let rval be GetValue(rref).
If Type(rval) is not Object, throw a TypeError exception.
If rval does not have a [[HasInstance]] internal method, throw a TypeError exception.
Return the result of calling the [[HasInstance]] internal method of rval with argument lval.

——->Not all objects will have [[HasInstance]] internal method, but functions.
console.log(Object instanceof {});
TypeError: Expecting a function in instanceof check, but got <Object>
*/
二、ECMA5.1 规范中 [[HasInstance]]
/*
how [[HasInstance]] has been defined in the ECMA 5.1 specification:
Assume F is a Function object.
When the [[HasInstance]] internal method of F is called with value V, the following steps are taken:

If V is not an object, return false.
Let O be the result of calling the [[Get]] internal method of F with property name “prototype”.
If Type(O) is not Object, throw a TypeError exception.
Repeat
Let V be the value of the [[Prototype]] internal property of V.
If V is null, return false.
If O and V refer to the same object, return true.
——->Take the prototype property of F and compare it
with the [[Prototype]] internal property of O until it becomes null or prototype of F is the same as O.
*/
三、ECMA5.1 规范中 [[prototype]]
/*
what is the [[prototype]] internal property:
All objects have an internal property called [[Prototype]].
The value of this property is either null or an object and is used for implementing inheritance.
Whether or not a native object can have a host object as its [[Prototype]] depends on the implementation.
Every [[Prototype]] chain must have finite length(that is, starting from any object,
recursively accessing the [[Prototype]] internal property must eventually lead to a null value).

——->We can get this internal property with the Object.getPrototypeOf function
*/
/*
[[HasInstance]] also talks about another property called prototype, which is specific to the Function objects.
The value of the prototype property is used to
initialise the [[Prototype]] internal property of a newly created object
before the Function object is invoked as a constructor for that newly created object.

——->when a function object is used as a constructor, a new object will be created
and the new object will have its internal [[Prototype]] initialized with this prototype property
——->function Test() {}
Test.prototype.print = console.log;
console.log(Object.getPrototypeOf(new Test()) === Test.prototype);
# true
*/
console.log(“——————————————————-” + “\n\n”);
四、分析过程
// 分析:

console.log(Object instanceof Function);
// true

// It will fetch Function.prototype first and it will try
// and find if that object is in the prototype hierarchy of Object. Let us see how that turns out
console.log(Function.prototype);
// [Function: Empty]
console.log(Object.getPrototypeOf(Object));
// [Function: Empty]
console.log(Object.getPrototypeOf(Object) === Function.prototype);
// true

//Since the Function.prototype matches the Object’s internal property [[Prototype]], it returns true
console.log(Function instanceof Object);
// true
console.log(Object.prototype);
// {}
console.log(Object.getPrototypeOf(Function));
// [Function: Empty]
console.log(Object.getPrototypeOf(Function) === Object.prototype);
// false
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
// {}
Object.getPrototypeOf(Object.getPrototypeOf(Function)) === Object.prototype
// true

//Here, first we get the Object.prototype, which is {}.
// Now it is trying to find if the same object {} is there in the Function’s prototype chain.
// Immediate parent of Function is and Empty function.
console.log(Object.getPrototypeOf(Function));
// [Function: Empty]

//It is not the same as Object.prototype
console.log(Object.getPrototypeOf(Function) === Object.prototype);
// false

//But the [[HasInstance]] algorithm doesn’t stop there. It repeats and gets up one more level
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
// {}

//And this is the same as Object.prototype. That is why this returns true.
console.log(“——————————————————-” + “\n\n”);
五、证明流程
console.log(Object instanceof Function); // true
console.log(Function instanceof Object); // true
console.log(Object.prototype);
// {}
console.log(Object.getPrototypeOf(Function));
// [Function: Empty]
console.log(Object.getPrototypeOf(Function) === Object.prototype);
// false
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
//{}
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)) === Object.prototype);
// true
console.log(Object.getPrototypeOf(Function));
//[Function: Empty]
console.log(Object.getPrototypeOf(Function) === Object.prototype);
// false
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
// {}
console.log(“——————————————————-” + “\n\n”);

正文完
 0