在对象或object.prototype上定义属性?

时间:2015-12-29 09:37:43

标签: javascript oop

我最近看过JavaScript代码,其中getter和setter方法在构造函数方法的prototype-object上定义。

例如:

Person.prototype.getFirstName = function() {
  return this.firstName;
}

这是对的吗?

我的意思是: 'this'指向调用该方法的对象的描述符。

当我打电话时会发生什么......

console.log(Person.getFirstName());

...没有事先制作对象?

此外:

是否有一般规则何时将属性附加到构造函数方法以及何时附加到prototype-object?

从我的观点来看,如果您不一定要创建一个对象,那么附加到原型是正确的。因为该方法不使用必须单独设置对象的对象的值。

3 个答案:

答案 0 :(得分:3)

  

当我打电话时会发生什么......

Class
     

...没有事先制作对象?

您收到错误,console.log(Person.getFirstName()); 没有Person属性。

  

是否有一般规则何时将属性附加到构造函数方法以及何时附加到prototype-object?

是:

如果希望方法在通过构造函数创建的对象上可用(例如,在getFirstName中的obj上),则将该方法放在构造函数' s {{1}上通过分配var obj = new Person()(不共享)上的属性,将对象(共享)或方法分配给构造函数中的对象。

如果您希望方法在构造函数本身上可用,那么某些内置JavaScript方法(如prototypethis)的方式将其分配给构造:

Date.parse

这些方法并不特定于构造函数创建的对象(Object.create中的Person.doSomething = function() { // ... }; 是对构造函数本身的引用,除非你做了一些使它不同的东西。)

如果您来自基于类的语言,那么非常宽松类比就是您在构造函数上分配给this对象的属性(包括方法)或者构造函数中的prototype实例属性,您分配给构造函数本身的是静态属性。这是一个非常宽松的比喻,但有时很有帮助。

这是旧ES5及早期语法中的完整示例:

this

在上面:

  • function Person(name) { this.getName = function() { return name; }; } Person.prototype.sayHello = function() { console.log("Hello, my name is " + this.getName()); }; Person.copy = function(other) { return new Person(other.getName()); }; // Usage example var joe = new Person("Joe"); joe.sayHello(); console.log("joe's name is " + joe.getName()); var joeagain = Person.copy(joe); joeagain.sayHello(); 可在getName创建的实例上使用。它是为每个对象单独创建的,不与其他实例共享。它让我们得到这个人的名字,在这个例子中它是只读的。

  • new PersonsayHello创建的实例上可用,因为它们是从原型继承而来的,原型由new Person从原型分配给它们new Person财产。它在实例之间共享。

  • Person.prototype在实例上不可用(copy会出错),它是joe.copy()本身的属性。在这种情况下,我们使用它来复制实例,但它可以用于任何事情。

答案 1 :(得分:0)

通过使用new关键字

实例化原型来继承原型

所以代码

var Person = function(){}
Person.prototype.getFirstName = function() {
  return this.firstName;
}

Person.prototype.firstName = "test";

console.log(Person.getFirstName()); // Throw Uncaught TypeError 

正确的方法是:

var Person2 = new Person()
Person2.getFirstName() // "test"

测试此对象:

所以Prototype的{​​{1}}设置为Person Person2的对象(继承)

这与Java或C#语言中的this类似。

答案 2 :(得分:0)

我个人并不喜欢在原型中添加getter,如果你想要的只是访问实例值。您已经可以通过实例访问这些值:

function Person(name) {
   this.firstname = name;
}
Person.prototype.getFirstname = function() {
   return this.firstname;
}
var p = new Person('o-o');
console.log(p.firstname); //o-o
console.log(p.getFirstname()); //o-o

您可以在原型中添加getter以传递不同的上下文:

var firstname = Person.prototype.getFirstname.call({firstname: 'other'});
console.log(firstname); // other

如果是这样,将getter添加到原型中以添加一些计算是有意义的:

Person.prototype.getFirstname = function() {
   return new Date().toISOString + ': ' + this.firstname;
};

如果该策略适合您的需求,您可以采用不同的方式编排代码:

var common = {
  getValue = function(propName) {
     return new Date().toISOString() + ': ' + this[propName];
  }
};

function Person(name) {
   this.firstname = name;
}

$.extend(Person.prototype, common); //jQuery extend
var p = new Person('o-o');
console.log(p.firstname); //o-o
console.log(p.getValue('firstname')); //today: o-o

使用通用的common扩展您的原型:在开发期间添加日志记录信息,并将这些多余的日志记录信息放入生产中。