Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/446.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript中的对等继承_Javascript - Fatal编程技术网

JavaScript中的对等继承

JavaScript中的对等继承,javascript,Javascript,在观看Douglas Crockford关于高级JavaScript的讲座时,他提出了寄生继承的概念,本质上就是让构造函数调用其他构造函数来修改所讨论的对象。这是他的密码: function gizmo(id, secret) { secret = secret || {}; secret.id = id; return { toString: function () { return "gizmo " + secret.id; } }; } fun

在观看Douglas Crockford关于高级JavaScript的讲座时,他提出了寄生继承的概念,本质上就是让构造函数调用其他构造函数来修改所讨论的对象。这是他的密码:

function gizmo(id, secret) {
  secret = secret || {};
  secret.id = id;
  return {
    toString: function () {
      return "gizmo " + secret.id;
    }
  };
}

function hoozit(id) {
  var secret = {},
      that = gizmo(id, secret);
  that.test = function (testid) {
    return testid === secret.id;
  };
  return that;
}

var myHoozit = hoozit(20);
console.log(myHoozit.test(20)); //returns true
我理解代码,这里没有太难掌握的东西。混淆发生在
hoozit
功能中。如果不设置
secret={}
,则不会返回a
true

这是令人困惑的,因为在
gizmo
函数中,您会看到
secret=secret | |{}
应该为我们解决这个问题。。。但事实并非如此

为什么当在
hoozit
函数中没有传递第二个参数(Chrome和Firefox都中断)时,
gizmo
函数中的短路不能正常工作

为什么当在
hoozit
函数中没有传递第二个参数(Chrome和Firefox都中断)时,
gizmo
函数中的短路不能正常工作

很简单,因为您无法访问
secret
中的
that.test
,因为它不在该范围内:

function hoozit(id) {
  var that = gizmo(id);
  that.test = function (testid) {
    // secret is not defined in this or in any higher scope
    // hence you get a refernece error
    return testid === secret.id;
  };
  return that;
}
存在的唯一
secret
对象是
gizmo
函数的本地对象


如果您定义它,只是不将它传递给
gizmo
,那么
secret=secret | |{}
将计算为
secret={}
,即在
gizmo
函数中创建一个新对象。该值只能在
gizmo
函数中访问,与
hoozit
函数中的
secret
变量完全无关。
gizmo
中的
secret
对象与
hoozit
中的对象不同

function hoozit(id) {
  var secret = {},      // secret object is created here
      that = gizmo(id);
  that.test = function (testid) {
    // you never set `secret.id`, hence the comparison results in `false`
    return testid === secret.id;
  };
  return that;
}


secret=secret | |{}
没有什么问题,它按预期工作。

让我们看一个简单的例子

function Foo(baz){
    baz = baz || {};
    baz.boo = 1;
}

function Bar(baz){
    baz = baz || {};
    Foo(baz);
    return baz;
}
如果我们调用
Bar()
,我们将向Foo传递一个对象。然后,它通过设置
boo
属性来解析对象。好极了

现在,假设我们的条形函数如下所示:

function Bar(baz){
    baz = baz || {};
    Foo();
    return baz;
}
唯一的区别是我们没有将对象传递给Foo。因此,Foo正在其作用域内创建一个对象。我们在新对象上设置一个属性,然后函数结束。该对象不是Bar的父范围,因此Bar永远不知道该对象已创建,也无法访问它。在接下来的几毫秒内,对象将从RAM中删除,因为没有对它的引用


你的问题并非如此。
toString
函数引用它。由于外部作用域已完成,因此它现在是
toString
函数的局部变量。如果我们没有传递
secret
对象,那么它永远不会离开该范围。它必须以某种方式出口

更合乎逻辑的策略是将其创建为原始对象的属性。我们的秘密很容易被知道JavaScript是什么的用户访问,所以我们应该省去一些麻烦,并使用合理的继承方法

如果您不知道
SomeFunction.call
可以接受任意数量的参数。第一个参数是您希望在函数中成为的
this
,其余参数只是常规参数

function gizmo() {
    this.toString = function () {
        return "gizmo " + this.id;
    };
};

function hoozit(id) {
    this.id = id;
    gizmo.call(this); // allow gizmo to manipulate this object

    this.test = function (is) {
        return this.id === is;
    };
};

h = new hoozit(1);
console.log(h.test(1)); // true
console.log(h.toString()); // "gizmo 1"

您需要
secret={}


它在
return testid===secret.id处出错因为
机密
需要存在

您可能正在寻找的主要魔法是,正在填充
secret.id
,因为所有操作都发生在
gizmo()
中。答案是这行:
that=gizmo(id,secret)

secret
被传递给gizmo,在JavaScript中,对象通过引用传递。这意味着,如果您有一个本地对象,并将该对象作为参数传递给另一个函数,则对该对象的任何操作都将在本地反映

如果不希望发生这种情况,则需要对参数进行某种复制/克隆(库错误地使用了克隆这个术语来表示深度复制)。但在本例中,您确实希望更改gizmo中的
secret
,以更新hoozit中的
secret
,因此一切都正常工作


下面是另一种书写方式:

function gizmo(secret) {              // only receive secret, which already has an "id"
   secret = secret || {'id':null};    // if secret not passed create it with a default "id"
   return {
      toString: function () {
         return "gizmo " + secret.id; // the reason why we needed a default "id"
      }
   };
}

function hoozit(id) {
   var secret = {'id':id},            // create a object and set key "id" to hoozit's argument
       that   = gizmo(secret);        // only pass secret

   that.test  = function (testid) {
      return testid === secret.id;
   };

   return that;
}

var myHoozit = hoozit(20);
console.log( myHoozit.test(20) ); //returns true

如果你不声明
秘密
,你怎么能在
hoozit.test
中测试
testid==secret.id
?@Zirak好吧,如果我们把它改成
那样的.id
我想如果短路像我们想象的那样工作,它会工作。如果你在hoozit没有这个,当调用gizmo时,它会抛出一个引用错误。你能发布你修改过的代码吗?你认为什么应该起作用?秘密不能交朋友!但是,为什么要使用私有变量呢?有人可以轻松地获取该代码,将其修改为成员变量,然后重新创建该类。通常的规则是把你想公开的东西都记录下来,其他的东西都是没有记录的,不应该使用。这对我不起作用。如果我在
hoozit
中取出
secret
,它就会破裂。@Sethen:这就是我要说的,我解释了原因,不是吗?让我困惑的是
secret=secret |{}
。。。这似乎不起作用?我正在调用gizmo,第二个参数中没有任何内容。我想我只是不理解这一点。我会假设这将与
that.id
一起工作,而不是
secret.id
,但它不工作。它正在工作。如果
secret
未定义的
secret=secret | |{}
基本上是
secret={}
,即它在
gizmo
内创建一个新对象。该对象不能从外部访问,它是函数的本地对象。我喜欢使用
call