Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/456.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,我倾向于用c风格编写Javascript类 例如,在C中,我们这样做 public class Parent { // stuff } public class Child : Parent { // Protected and public stuff from Parent will be accessible } 在JS中,我通过使用proto找到了与此等效的示例 var namespace = namespace || {}; namespace.Parent =

我倾向于用c风格编写Javascript类

例如,在C中,我们这样做

public class Parent {
    // stuff
}

public class Child : Parent {
    // Protected and public stuff from Parent will be accessible
}
在JS中,我通过使用proto找到了与此等效的示例

var namespace = namespace || {};

namespace.Parent = function() {

    // Public variables
    self.pubVariable = "I am accessible";

    // Private variables
    var priVariable = "I'm not accessible outside of self";

    // ctor
    function self() {}

    return self;
}


namespace.Child = (function() {
    this.__proto__ = new namespace.Parent();

    // ctor
    function self() {}

    self.init = function() {
        // Prints the pubVariable
        console.log(pubVariable);
    };

    return self;

})($);

// Call it (statically)    
namespace.Child.init();

虽然这是可行的,但它只是Webkit和Mozilla。我知道使用原型可以实现这一点,但不知道如何实现。任何建议都将不胜感激。谢谢

对于父/子类,我会这样做

// your parent class
var Parent = function() {

  // parent constructor
  console.log("parent constructor!");

  // some public properties
  this.foo = "foo";
  this.bar = "bar";

  // a private data member
  var secret = "123456";
};

// a parent function
Parent.prototype.something = function() {
  console.log("something!");
}

// your child class
var Child = function() {

  // call parent constructor
  Parent.call(this);    

  // child constructor
  console.log("child constructor!");

  // override bar
  this.bar = "override!";
};

// the magic!
// child prototype build from parent prototype
Child.prototype = Object.create(Parent.prototype, {constructor: {value: Child}});
namespace.Parent = function() { //... }
namespace.Parent.prototype.aMethodInParent = function(){ //... };
namespace.Child = function() { // ... };
namespace.Child.prototype = new namespace.Parent();
示例用法

var c = new Child();
c.something();
// => parent constructor!
// => child constructor!
// => something!

c.foo //=> "foo"
c.bar //=> "override!"
如果使用名称空间,则概念是相同的

您可以在许多库中看到这种模式

编辑

根据您的评论,这里是和添加的演示

var Foo = function(){};
Foo.prototype.hello = function(){ return "hello!"; };
var foo = new Foo();

// call our hello method
// this calls foo.__proto__.hello
foo.hello(); //=> "hello!"

// override `hello` method for this instance
foo.hello = function(){ return "こんにちは"; };

// call our hello method again
// this calls foo.hello because it is defined directly on our instance
// (it has a higher precedence in the lookup chain)
foo.hello(); //=> "こんにちは"

// remove the override
delete foo.hello;

// call our hello method again
// this goes back to calling foo.__proto__.hello
foo.hello(); //=> "hello!"

// remove the method prototype
delete Foo.prototype.hello

// call our hello method one last time
// spoiler: it's gone!
foo.hello(); //=> TypeError: Object [object Object] has no method 'hello'
如您所见,通过使用this.something=function{};在实例上直接定义方法,您将失去此功能;。我个人更喜欢在原型上定义方法,因为它增加了灵活性。这样,原型的工作原理就像蓝图一样。您可以获得所有预定义的行为;您可以根据需要进行修改,并随时恢复到原始状态,所有这些都是基于每个实例的

还有一件事

在上一个示例中,我们有一个原型方法和一个实例方法覆盖。是否也有方法调用原始方法?让我看看

var Foo = function(){};
Foo.prototype.hello = function(){ return "hello!"; };

var foo = new Foo();
foo.hello = function(){ return "こんにちは!"; }

// call override method
foo.hello(); //=> "こんにちは!"

// call original method
Foo.prototype.hello.call(foo); //=> "hello!"

// japanese just one more time...
foo.hello(); //=> "こんにちは!" 
这也行,但我从来没有真正的需要。我认为这样做的好处是,您不需要通过这种方式了解原始类:

// call original method from the instance
foo.__proto__.hello.call(foo); //=> "hello!"

原型

对于父/子类,我会这样做

// your parent class
var Parent = function() {

  // parent constructor
  console.log("parent constructor!");

  // some public properties
  this.foo = "foo";
  this.bar = "bar";

  // a private data member
  var secret = "123456";
};

// a parent function
Parent.prototype.something = function() {
  console.log("something!");
}

// your child class
var Child = function() {

  // call parent constructor
  Parent.call(this);    

  // child constructor
  console.log("child constructor!");

  // override bar
  this.bar = "override!";
};

// the magic!
// child prototype build from parent prototype
Child.prototype = Object.create(Parent.prototype, {constructor: {value: Child}});
namespace.Parent = function() { //... }
namespace.Parent.prototype.aMethodInParent = function(){ //... };
namespace.Child = function() { // ... };
namespace.Child.prototype = new namespace.Parent();
示例用法

var c = new Child();
c.something();
// => parent constructor!
// => child constructor!
// => something!

c.foo //=> "foo"
c.bar //=> "override!"
如果使用名称空间,则概念是相同的

您可以在许多库中看到这种模式

编辑

根据您的评论,这里是和添加的演示

var Foo = function(){};
Foo.prototype.hello = function(){ return "hello!"; };
var foo = new Foo();

// call our hello method
// this calls foo.__proto__.hello
foo.hello(); //=> "hello!"

// override `hello` method for this instance
foo.hello = function(){ return "こんにちは"; };

// call our hello method again
// this calls foo.hello because it is defined directly on our instance
// (it has a higher precedence in the lookup chain)
foo.hello(); //=> "こんにちは"

// remove the override
delete foo.hello;

// call our hello method again
// this goes back to calling foo.__proto__.hello
foo.hello(); //=> "hello!"

// remove the method prototype
delete Foo.prototype.hello

// call our hello method one last time
// spoiler: it's gone!
foo.hello(); //=> TypeError: Object [object Object] has no method 'hello'
如您所见,通过使用this.something=function{};在实例上直接定义方法,您将失去此功能;。我个人更喜欢在原型上定义方法,因为它增加了灵活性。这样,原型的工作原理就像蓝图一样。您可以获得所有预定义的行为;您可以根据需要进行修改,并随时恢复到原始状态,所有这些都是基于每个实例的

还有一件事

在上一个示例中,我们有一个原型方法和一个实例方法覆盖。是否也有方法调用原始方法?让我看看

var Foo = function(){};
Foo.prototype.hello = function(){ return "hello!"; };

var foo = new Foo();
foo.hello = function(){ return "こんにちは!"; }

// call override method
foo.hello(); //=> "こんにちは!"

// call original method
Foo.prototype.hello.call(foo); //=> "hello!"

// japanese just one more time...
foo.hello(); //=> "こんにちは!" 
这也行,但我从来没有真正的需要。我认为这样做的好处是,您不需要通过这种方式了解原始类:

// call original method from the instance
foo.__proto__.hello.call(foo); //=> "hello!"
原型

我想,你想要这个

// namespace
var namespace = namespace || {};

// Parent Class
namespace.Parent = function() {
    this.pubVariable = "I am accessible";
    var priVariable = "I'm not accessible outside of this";
}

// Child class
namespace.Child = function() {
    // namespace.Parent.call(this);
    this.init = function()
    {
        // returns Parent class' pubVariable
        // inherited by namespace.Child.prototype
        return this.pubVariable;
    }
};

// inherit Parent class
namespace.Child.prototype = new namespace.Parent();

var kid = new namespace.Child();
console.log(kid.init()); // I am accessible
若您使用namespace.Parent.callthis,那个么子类将拥有它自己的pubVariable副本,但现在子类正在使用父类的pubVariable

另外,如果您想与子类共享来自父类的方法,那么应该在父类的原型中添加方法,如下所示

// your parent class
var Parent = function() {

  // parent constructor
  console.log("parent constructor!");

  // some public properties
  this.foo = "foo";
  this.bar = "bar";

  // a private data member
  var secret = "123456";
};

// a parent function
Parent.prototype.something = function() {
  console.log("something!");
}

// your child class
var Child = function() {

  // call parent constructor
  Parent.call(this);    

  // child constructor
  console.log("child constructor!");

  // override bar
  this.bar = "override!";
};

// the magic!
// child prototype build from parent prototype
Child.prototype = Object.create(Parent.prototype, {constructor: {value: Child}});
namespace.Parent = function() { //... }
namespace.Parent.prototype.aMethodInParent = function(){ //... };
namespace.Child = function() { // ... };
namespace.Child.prototype = new namespace.Parent();
那么,当您在这样的子类中继承它时

// your parent class
var Parent = function() {

  // parent constructor
  console.log("parent constructor!");

  // some public properties
  this.foo = "foo";
  this.bar = "bar";

  // a private data member
  var secret = "123456";
};

// a parent function
Parent.prototype.something = function() {
  console.log("something!");
}

// your child class
var Child = function() {

  // call parent constructor
  Parent.call(this);    

  // child constructor
  console.log("child constructor!");

  // override bar
  this.bar = "override!";
};

// the magic!
// child prototype build from parent prototype
Child.prototype = Object.create(Parent.prototype, {constructor: {value: Child}});
namespace.Parent = function() { //... }
namespace.Parent.prototype.aMethodInParent = function(){ //... };
namespace.Child = function() { // ... };
namespace.Child.prototype = new namespace.Parent();
另一个小班/儿童班

namespace.AnotherChild = function() { // ... };
namespace.AnotherChild.prototype = new namespace.Parent();
在这种情况下,两个子/子类都将使用来自其父类的相同aMethodInParent方法

我想,你想要这个

// namespace
var namespace = namespace || {};

// Parent Class
namespace.Parent = function() {
    this.pubVariable = "I am accessible";
    var priVariable = "I'm not accessible outside of this";
}

// Child class
namespace.Child = function() {
    // namespace.Parent.call(this);
    this.init = function()
    {
        // returns Parent class' pubVariable
        // inherited by namespace.Child.prototype
        return this.pubVariable;
    }
};

// inherit Parent class
namespace.Child.prototype = new namespace.Parent();

var kid = new namespace.Child();
console.log(kid.init()); // I am accessible
若您使用namespace.Parent.callthis,那个么子类将拥有它自己的pubVariable副本,但现在子类正在使用父类的pubVariable

另外,如果您想与子类共享来自父类的方法,那么应该在父类的原型中添加方法,如下所示

// your parent class
var Parent = function() {

  // parent constructor
  console.log("parent constructor!");

  // some public properties
  this.foo = "foo";
  this.bar = "bar";

  // a private data member
  var secret = "123456";
};

// a parent function
Parent.prototype.something = function() {
  console.log("something!");
}

// your child class
var Child = function() {

  // call parent constructor
  Parent.call(this);    

  // child constructor
  console.log("child constructor!");

  // override bar
  this.bar = "override!";
};

// the magic!
// child prototype build from parent prototype
Child.prototype = Object.create(Parent.prototype, {constructor: {value: Child}});
namespace.Parent = function() { //... }
namespace.Parent.prototype.aMethodInParent = function(){ //... };
namespace.Child = function() { // ... };
namespace.Child.prototype = new namespace.Parent();
那么,当您在这样的子类中继承它时

// your parent class
var Parent = function() {

  // parent constructor
  console.log("parent constructor!");

  // some public properties
  this.foo = "foo";
  this.bar = "bar";

  // a private data member
  var secret = "123456";
};

// a parent function
Parent.prototype.something = function() {
  console.log("something!");
}

// your child class
var Child = function() {

  // call parent constructor
  Parent.call(this);    

  // child constructor
  console.log("child constructor!");

  // override bar
  this.bar = "override!";
};

// the magic!
// child prototype build from parent prototype
Child.prototype = Object.create(Parent.prototype, {constructor: {value: Child}});
namespace.Parent = function() { //... }
namespace.Parent.prototype.aMethodInParent = function(){ //... };
namespace.Child = function() { // ... };
namespace.Child.prototype = new namespace.Parent();
另一个小班/儿童班

namespace.AnotherChild = function() { // ... };
namespace.AnotherChild.prototype = new namespace.Parent();
在这种情况下,两个子/子类都将使用来自其父类的相同aMethodInParent方法


为什么你要为孩子而不是为父母使用生命?这段代码似乎永远都不起作用。为什么要用一种完全不同的类系统语言编写类呢?javascript类可以像C类或经典类那样工作,但是你会发现,停止与之对抗,顺其自然要容易得多。@Bergi,代码在webkit/moz中运行得很好。所有来自父对象的公共变量和方法都可以在子对象中访问。@tkone,将来自父对象的方法和变量包含在子对象中是一种非常好的方法,为什么不呢?@EricHerlitz:如果这真的有效,那么你滥用了很多东西。基本上,您将全局对象的原型设置为父对象的self函数,其属性作为变量随处可见。这是完全错误的。为什么你要为孩子而不是为父母使用生命?这段代码似乎永远都不起作用。为什么要用一种完全不同的类系统语言编写类呢?javascript类可以像C类或经典类那样工作,但是你会发现,停止与之对抗,顺其自然要容易得多。@Bergi,代码在webkit/moz中运行得很好。所有来自父对象的公共变量和方法都可以在子对象中访问。@tkone,将来自父对象的方法和变量包含在子对象中是一种非常好的方法,为什么不呢?@EricHerlitz:如果这真的有效,那么你滥用了很多东西。基本上你是在设定
全局对象的原型是父对象的自函数,其属性作为变量随处可见。这是完全错误的;如果您能对私有变量和公共属性以及它们是如何继承的稍加评论,那就太好了。我创建了一个fiddle,使用与您相同的行为,而不是将原型方法“something”放在父类中,有理由不这样做吗@EricHerlitz,它们的运作非常相似,在这里你很可能不会遇到问题。区别在于,我的附加到Parent.prototype,而你的附加到myParent父类的一个实例。我更喜欢将实例函数附加到原型上,然后在必要时直接在实例上定义实例级重写。@EricHerlitz,我再次更新了我的答案,以更好地演示原型的威力:>+1;如果您能对私有变量和公共属性以及它们是如何继承的稍加评论,那就太好了。我创建了一个fiddle,使用与您相同的行为,而不是将原型方法“something”放在父类中,有理由不这样做吗@EricHerlitz,它们的运作非常相似,在这里你很可能不会遇到问题。区别在于,我的附加到Parent.prototype,而你的附加到myParent父类的一个实例。我更喜欢将实例函数附加到原型上,然后在必要时直接在实例上定义实例级重写。@EricHerlitz,我又更新了一次我的答案,以便更好地演示原型的威力:>完全正确!这允许我将方法和类的子集分离到它们自己的对象中,同时仍然能够访问parent.Right的优点。如果要与子类共享方法,则必须在父类的原型中添加方法。不要使用new来继承父类!你能解释为什么不是新的吗?没错!这允许我将方法和类的子集分离到它们自己的对象中,同时仍然能够访问parent.Right的优点。如果要与子类共享方法,则必须在父类的原型中添加方法。不要使用new来继承父类!你能解释为什么不是新的吗?