使用__proto__进行简单的javascript委派

时间:2012-06-18 00:26:28

标签: javascript inheritance prototype

我习惯于Java,所以当我尝试这样的事情时:

function subSection(pattern){
    this.total = 0;
    this.pattern = pattern;
    this.distance=0;
}

function enhancer(pattern){
    __proto__:subSection;
    this.pattern = pattern;
}

function silencer(pattern){
    __proto__:subSection;
    this.pattern = pattern;
}

var a = new enhancer("aaa");
document.write(a.distance)

我得到“未定义”。我以为我继承了总数和距离数据成员

4 个答案:

答案 0 :(得分:3)

不要使用__proto__,它是Mozilla专有属性(由其他一些人复制)并且已被弃用。分配给construtor.prototpye。

该行:

> __proto__:subSection;

没有为任何东西赋值,它是一个标签(__proto__),后跟一个语句subSection,它是对未分配给任何东西的subSection函数的引用。

你似乎不理解原型继承,试试Douglas Crockford的Prototypal Inheritance in JavaScript

以下可能类似于您要做的事情,这里必须有一千个类似的问题:

function SubSection(pattern) {
    this.pattern = pattern;
    this.total = 0;
    this.distance=0;
}

// Add a method to subSection.prototype
SubSection.prototype.getDistance = function() {
  return this.distance;
}

function Enhancer(pattern) {
    this.pattern = pattern;
}

// To make enhancer inherit from subSection, make its prototype
// an instance of subSection
Enhancer.prototype = new SubSection();

var a = new Enhancer("aaa");

document.write(a.getDistance()); // 0

哦,按照惯例,构造函数名称以大写字母开头。

答案 1 :(得分:3)

function subSection(pattern){
    this.total = 0;
    this.pattern = pattern;
    this.distance=100;
}

function enhancer(pattern){
    this.__proto__=new subSection(pattern);
}

function silencer(pattern){
    this.__proto__=new subSection(pattern);
}

var a = new enhancer("aaa");
document.write(a.distance)​;

但它只是RobG所说的Mozilla专有财产。

DEMO.

<强>更新

function subSection(pattern){
    this.total = 0;
    this.pattern = pattern;
    this.distance=100;
}

function enhancer(pattern){
    function F(){};
    F.prototype = new subSection(pattern); // inherited subSection
    return new F();    
}

function silencer(pattern){
    function F(){};
    F.prototype = new subSection(pattern); // inherited subSection
    return new F();
}

var a = new enhancer("aaa");
document.write(a.distance)​;

DEMO.

有用的链接: herehere

答案 2 :(得分:0)

你应该为你的对象使用原型继承。我会把你的增强器对象定义为:

    //create Enhancer object
function Enhancer(pattern){
    this.subSection(pattern);    
}

//extend Enhancer with object methods
Enhancer.prototype = {

   subSection: function(pattern){
         this.pattern = pattern;
         this.total = 0;        
         this.distance=0;
  }

};

所以这就是我在这段代码中的目的:

  1. 我正在使用函数定义Enhancer对象。注意我大写“Enhancer”来表示这个数据结构的“对象”。
  2. 我将传递给对象的“pattern”值用于调用Enhancer.subSection();我可以调用.subSection()作为Enhancer对象的方法,因为我将它定义为.prototype的方法。
  3. 这是这种方法的工作fiddle example

答案 3 :(得分:0)

一般来说,totaldistance之类的属性应该在subSection prototype上定义,以便为prototype对象的每个实例初始化为完全相同的值。而不是在构造函数中。

对象的prototype基本上是一个“模板”,该对象的每个实例都基于该模板。每个实例都在function subSection(pattern) { this.pattern = pattern; } function enhancer(pattern) { this.pattern = pattern; } function silencer(pattern) { this.pattern = pattern; } 上定义了每个属性和方法。

因此,三个“类”(JavaScript没有经典继承语言中定义的类,如Java,但有时习惯这些语言的人更容易使用术语)应声明如下:

total

distancesubSection移出subSection构造函数并进入subSection.prototype.total = 0; subSection.prototype.distance = 0; 原型:

subSection

下一步是使用no-op函数作为它们之间的一种代理,在enhancersilencerfunction fn() {} fn.prototype = subSection.prototype; enhancer.prototype = new fn(); silencer.prototype = new fn(); 之间设置原型继承:

constructor

最后,将enhancersilencer原型的constructor属性设置为正确的对象,以便实例'enhancer属性引用正确的构造函数。如果我们不采取此步骤,则silencersubSection的任何实例都将错误地引用enhancer.prototype.constructor = enhancer; silencer.prototype.constructor = silencer; 构造函数。

enhancer

现在我们可以实例化silencertotal个对象,生成的实例将具有distanceconstructor属性以及var a, b; a = new enhancer('aaaa'); b = new silencer('bbbb'); console.log(a.total + ', ' + a.distance); // 0, 0 console.log(b.total + ', ' + b.distance); // 0, 0 console.log(a.constructor); // (string representation of enhancer constructor) 属性是指各自的对象。

fn

我们在继承过程中使用function Person(name, age, hometown) { this.name = name; this.age = age; this.hometown = hometown; } function Employee(name, company, title) { this.name = name; this.company = company; this.title = title; } 函数作为代理的原因是因为对象应该能够从另一个不一定具有相同构造函数参数集的对象继承。

假设我们有以下两个构造函数:

Employee

Person应该能够继承Employee.prototype,即使它们不共享同一组构造函数参数。如果我们只是将Person设置为等于Employee的新实例,则name原型会有三个未定义的属性agehometownEmployee.prototype = new Person; // name, age and hometown are undefined var e = new Employee('John Smith', 'New York Times', 'editor'); // e's prototype has undefined properties name, age and hometown

fn

通过使用no-op函数fn(我们可以将它命名为我们想要的任何东西),我们最终为每个实例提供了一个干净的原型,因为构造函数不期望{{1}}任何争论。

这不是必需的,但它是一种更简洁的方式来设置原型继承:没有太多理由使具有未定义属性的原型混乱。