Object.create vs new

时间:2016-07-29 17:33:02

标签: javascript prototype javascript-objects javascript-inheritance

以下代码在我使用构造函数创建对象时有效,但是当我执行object.Create时,它无法正确初始化。 functionName is not a function。我有两个问题。为什么object.create不起作用?

如何在同一个计算器函数中组织我的代码,以便我可以使用new和object.create?

我知道我可以将方法添加到Calculator.prototype并执行Object.create,但我想知道我的代码是否可以在当前结构中更改以允许两者兼而有之?

//var calc = new Calculator();
var calc = Object.create(Calculator);


function Calculator(){
    this.array = [];
    this.results = 0;

    this.calculate = function(){    
        try{
        results = eval(this.array.join(''));
        this.array = [results];
        return results; 
        }
        catch(error){
            alert('Wrong arguments provided');
            return this.array.join('');
        }
    },

    this.isNumber = function(str){
        return !isNaN(parseFloat(str)) && isFinite(str);
    },

    this.addToOperationsArray = function(str){
        if (this.array.length <= 0 && !this.isNumber(str)){ // Don't add operand before any number.
            return; 
        }

        this.array.push(str);

    },
    this.clearEverything = function(){
        this.array = [];
    }
}

3 个答案:

答案 0 :(得分:3)

Object.create没有构造函数调用。

您可以通过多种方式获得类似的结果。看看这些内容是否有助于你:

function Calculator() {
  this.array = [];
  this.results = 0;
}
Calculator.prototype = {
  calculate: function() {
    try {
      results = eval(this.array.join(''));
      this.array = [results];
      return results;
    } catch (error) {
      alert('Wrong arguments provided');
      return this.array.join('');
    }
  },
  isNumber: function(str) {
    return !isNaN(parseFloat(str)) && isFinite(str);
  },
  addToOperationsArray: function(str) {
    if (this.array.length <= 0 && !this.isNumber(str)) { // Don't add operand before any number.
      return;
    }

    this.array.push(str);

  },
  clearEverything: function() {
    this.array = [];
  }
};

// create using 'new'
var calc1 = new Calculator();

// create using 'Object.create'
// the constructor function is not called
// but properties of returned object can be passed to the function, and
// you can control the enumerable, writable, configurable properties
var calc2 = Object.create(Calculator.prototype, {
  'array': {
    value: [],
    enumerable: true
  },
  'results': {
    value: 0,
    enumerable: true
  }
});

// create using 'Object.create'
// and invoke the constructor with 'call',
// explicitly setting 'this'
var calc3 = Object.create(Calculator.prototype);
Calculator.call(calc3);


console.log(calc1);   // Calculator {array: Array[0], results: 0}
console.log(calc2);   // Object {array: Array[0], results: 0}
console.log(calc3);   // Object {array: Array[0], results: 0}

答案 1 :(得分:2)

Object.create() //This for inherit the parent object

你想要的是实例化对象,你可以这样做:

var calc = new Calculator() //This will inherit it's prototype and execute the constructor for you.

Object.create 并排使用。只是为了让更清楚关于原型继承和实例化,让我们退一步,我将为您提供示例

// CREATE || Object.create for inheritence by prototyping
var Thing = function (name) {
  this.type = "universal";
  this.name = name;
}

Thing.prototype = {
  say: function(something) {
    console.log(this.name + " say something " + something);
  },
  check_soul: function (){
    console.log(this.name + " soul is " + this.type);
  }
}

// constructor for God
var God = function(name){
  Thing.call(this, name); // Execute parent constructor also with current context
  this.type = "pure"; // overwrite the type
}

God.prototype = Object.create(Thing.prototype); // inherit God from Thing
God.prototype.constructor = God; // implement the constructor


// constructor for Demon
var Demon = function(name){
  Thing.call(this, name);
  this.type = "corrupted";
}

Demon.prototype = Object.create(Thing.prototype, {
  say: {
    value: function(something){ // Overwrite Thing prototype for say
    console.info(this.name + " say: Let's destory " + something + "!");
  }}
}); // inherit Demon from Thing
Demon.prototype.constructor = Demon;

/////////////////////////////////////////////////////////////////////////////////////
// NEW || new for instantiation
var anonymous = new Thing("Anonymous");
anonymous.check_soul();

var god = new God("Zeus");
god.check_soul();
god.say("omni");

var demon = new Demon("Lucifer");
demon.check_soul();
demon.say("human");

上面的例子太冗长了吗? (ES2015在这里提供帮助)请注意,这只适用于节点v6及更高版本。

// CREATE || Object.create for inheritence by prototyping

'use strict';

class Thing {
  constructor (name){
    this.type = "universal";
    this.name = name;
  }

  say(something) {
    console.log(this.name + " say something " + something);
  }

  check_soul() {
    console.log(this.name + " soul is " + this.type);
  }
}

class God extends Thing { // inherit God from Thing and implement the constructor
  constructor (name){
    super(name); // Execute parent constructor also with current context
    this.type = "pure"; // overwrite the type
  }
}

class Demon extends Thing { // inherit Demon from Thing and implement the constructor
  constructor (name){
    super(name); // Execute parent constructor also with current context
    this.type = "corrupted"; // overwrite the type
  }

  say(something) { // Overwrite Thing prototype for say
    console.info(this.name + " say: Let's destory " + something + "!");
  }
}


/////////////////////////////////////////////////////////////////////////////////////
// NEW || new for instantiation
var anonymous = new Thing("Anonymous");
anonymous.check_soul();

var god = new God("Zeus");
god.check_soul();
god.say("omni");

var demon = new Demon("Lucifer");
demon.check_soul();
demon.say("human");

答案 2 :(得分:0)

有点晚了,可能你已经注意到了,但是在你的实现中,在代码Calculator.prototype.constructor中至少有一个副作用,这将指向Object.prototype.constructor而不是Calculator构造函数,什么是你做的是覆盖原型链的每个属性,最好使用点表示法来添加新属性Calculator.prototype.method = () => { // some code }