instanceof检查在子类没有设置构造函数 [英] instanceof check works on subclass without setting constructor

查看:236
本文介绍了instanceof检查在子类没有设置构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下JavaScript代码

  function Parent(){
}

function Child(){
}

Child.prototype = Object.create(Parent.prototype);

注意不存在语句

  Child.prototype.constructor = Child; 

我的理解是,由于构造函数属性未设置实例检查对于 Child 类的新实例应该失败。

  var child = new Child(); 
child instanceof Child; //应该给假的



我验证了构造函数设置不正确



但是当我运行 child instanceof Child >



但它应该是 false 原型未设置 p>

环境

  Google Chrome 48.0版。 2564.109(64位)
Ubuntu 14.04 LTS


解决方案

< blockquote>

我的理解是,由于未设置构造函数属性,instanceof检查对于Child类的新实例应该失败。


不,这不正确。事实上,直到ES2015(aka ES6),构造函数属性不是用于JavaScript本身的任何东西。它被定义为存在于默认对象上,运行时分配给函数的原型属性,但不是 used



instanceof 不关心 construtor 。考虑:

  o instanceof Foo 

instanceof 将查看对象 Foo.prototype 是否指向任何位置 o 的原型链。 (如果原型链不是一个熟悉的术语,请参见*在答案的结尾,然后回来。)如果是,它返回 true ;如果没有,它返回 false



例如,这里是一个概念实现 instanceof ,手动挥动一些细节:

  function isAnInstance(obj,func){
var p;
for(p = Object.getPrototypeOf(obj); p; p = Object.getPrototypeOf(p)){
if(p === func.prototype){
return true;
}
}
return false;
}

虽然它已被ES2015规格所取代,我将链接到ES5因为它是用更易于访问的语言编写的,而且这个方面没有改变: instanceof 有效地只是调用函数的 [[HasInstance]] 内部方法,此处定义



我们可以看到构造函数不涉及你的问题,也是从这个简单的演示:



  var p = {}; var o = Object.create(p); var Foo = function(){}; Foo.prototype = p; snippet.log (Foo的实例); // true  

  snippet`物件,请参阅http://meta.stackexchange.com/a/242144/134069  - >< script src =// tjcrowder.github.io/simple-snippets-console/snippet.js\"> < / script>  



请注意:


  1. o 未通过 Foo

  2. 事实上, Foo 甚至在 o $ <$> $ ,并且其原型没有构造函数 code>属性

... instanceof 说:是的,看起来像是一个Foo。 :-)纯粹是因为对象 Foo.prototype 指向也在 o 的原型链。






* 原型链



你清楚地知道,JavaScript中的对象有原型,他们继承属性。这些原型是对象,因此他们有原型。



考虑一个两层的(可以说是三层)继承层次结构,这里是ES5:

  function Base(){
}

函数Derived b Base.call(this);
}
Derived.prototype = Object.create(Base.prototype);
Derived.prototype.constructor = Derived;

...或在ES2015中:

  class Base {
}
class Derived extends Base {
}

现在我们使用它:

  var d = new Derived 

d object和下面的类似,我当然的意思是对象 d 是指 —但是真的很冗长。) / p>

现在, d 对象的原型是 Derived.prototype Derived.prototype 的原型是 Base.prototype Base.prototype 的原型是 Object.prototype Object.prototype 没有原型(它的 [[Prototype]] 内部槽是 底层 d c $ c>,它们意味着 d instanceof Object instanceof Base instanceof Derived


I have the following JavaScript code

function Parent() {
}

function Child() {
}

Child.prototype = Object.create(Parent.prototype);

Note the absence of the statement

Child.prototype.constructor = Child;

My understanding is that as the constructor property has not been set the instanceof checks should fail for new instances of Child class.

var child = new Child();
child instanceof Child; //Should give false

I verified that the constructor is incorrectly set

But when I run child instanceof Child it gave me true

But it should be false as constructor property is not set on Child's prototype to be Child.

Environment

Google Chrome Version 48.0.2564.109 (64-bit)
Ubuntu 14.04 LTS

解决方案

My understanding is that as the constructor property has not been set the instanceof checks should fail for new instances of Child class.

No, that's incorrect. In fact, until ES2015 (aka ES6), the constructor property wasn't used for anything at all in JavaScript itself. It was defined as existing on the default objects the runtime assigns to the prototype property on functions, but not used.

instanceof doesn't care about construtor at all. Consider:

o instanceof Foo

instanceof will look to see if the object Foo.prototype points to is anywhere on o's prototype chain. (If "prototype chain" is not a familiar term, see the * at the end of the answer and then come back.) If so, it returns true; if not, it returns false.

E.g., here's a conceptual implementaton of instanceof, hand-waving away some details:

function isAnInstance(obj, func) {
    var p;
    for (p = Object.getPrototypeOf(obj); p; p = Object.getPrototypeOf(p)) {
        if (p === func.prototype) {
            return true;
        }
    }
    return false;
}

Although it's been superceded by the ES2015 spec, I'll link to the ES5 spec because it's written in more accessible language and this aspect hasn't changed: instanceof effectively just calls a function's [[HasInstance]] internal method, defined here.

We can see that constructor isn't involved from your question, and also from this simple demonstration:

var p = {};
var o = Object.create(p);
var Foo = function() {};
Foo.prototype = p;
snippet.log(o instanceof Foo); // true

<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Note that:

  1. o wasn't created via Foo
  2. In fact, Foo didn't even exist until after o was created
  3. o and its prototype don't have a constructor property at all

...and yet instanceof says "Yep, looks like it's a Foo." :-) Purely because the object Foo.prototype points to is also on o's prototype chain.


* "prototype chain"

You clearly know that objects in JavaScript have prototypes from which they inherit properties. Those prototypes are objects, and so they have prototypes. So you get a "chain" of prototypes.

Consider a two-level (arguably three-level) inheritance hierarchy, here in ES5:

function Base() {
}

function Derived() {
    Base.call(this);
}
Derived.prototype = Object.create(Base.prototype);
Derived.prototype.constructor = Derived;

...or in ES2015:

class Base {
}
class Derived extends Base {
}

Now we use it:

var d = new Derived();

(Where you see "the d object" and similar in the below, I do of course mean "the object d refers to" — but that's really verbose.)

Now, the d object's prototype is Derived.prototype. Derived.prototype's prototype is Base.prototype. Base.prototype's prototype is Object.prototype. Object.prototype doesn't have a prototype (its [[Prototype]] internal slot is null).

Those objects are the prototype chain underlying d, and they mean that d is instanceof Object, instanceof Base, and instanceof Derived.

这篇关于instanceof检查在子类没有设置构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆