同事向我展示了下一个代码,这让我大吃一惊:
const x = Object.create(function() {});
// variant: const x = Object.create(Array);
console.log(x.call) // ƒ call() { [native code] }
console.log(typeof x.call) // "function"
console.log(x.call instanceof Function) // true
x.call() // Uncaught TypeError: x.call is not a function
我了解x.call
是来自function
的原型,它不属于x
的属性:
x.hasOwnProperty('call') // false
但为什么x.call
实际上无法执行?它与call keyword有关吗?
答案 0 :(得分:2)
原因x
是从call
继承Function.prototype
的对象,但是call
意味着要在函数上调用,因此如果您尝试执行它会失败在一个普通的对象上。
答案 1 :(得分:2)
Object.create背后的核心思想归结为:
function create(prt){
var noOP = function(){};
noOP.prototype = prt;
return new noOP;
}
因此,返回的值不是函数,而是一个对象。为了说明,我将首先存储一个函数:
var u = function(){return 5}
现在我将Object.create
使用它:
var res = create(u);
安慰它会给你>noOP {}
,所以它是一个普通的对象。问题从这里开始:
res.hasOwnProperty("prototype") //false
所以新创建的对象有" prototype"但这实际上是从u
继承的:
res.prototype === u.prototype //true
相似,"打电话"再次继承自u,而u又继承自其构造函数(Function)原型:
res.call === u.call //true
res.call === Function.prototype.call //also true
这是你的问题,如果你看一下call
的EcmaScript实现,它应该可以调用this
和this
。从call
:
res
var x = res.call; //ƒ call() { [native code] }
现在我会打电话给#34;在调用中,我们将传递3个参数,第1个用于调用,第2个用于设置this
在可调用内部,第3个用于调用可调参数的参数:
x.call(function(a){console.log("hey");console.log(a);console.log(this);},5,5)
//hey
//5
//Number {5}
现在,通过res
或res.call
在您创建的对象x.call
上尝试相同的操作:
x.call(res,5,5) //TypeError: x.call is not a function
最后,它归结为来自Object.create
的返回对象不可调用。