我最近看过JavaScript代码,其中getter和setter方法在构造函数方法的prototype-object上定义。
例如:
Person.prototype.getFirstName = function() {
return this.firstName;
}
这是对的吗?
我的意思是: 'this'指向调用该方法的对象的描述符。当我打电话时会发生什么......
console.log(Person.getFirstName());
...没有事先制作对象?
此外:
是否有一般规则何时将属性附加到构造函数方法以及何时附加到prototype-object?
从我的观点来看,如果您不一定要创建一个对象,那么附加到原型是正确的。因为该方法不使用必须单独设置对象的对象的值。
答案 0 :(得分:3)
当我打电话时会发生什么......
Class
...没有事先制作对象?
您收到错误,console.log(Person.getFirstName());
没有Person
属性。
是否有一般规则何时将属性附加到构造函数方法以及何时附加到prototype-object?
是:
如果希望方法在通过构造函数创建的对象上可用(例如,在getFirstName
中的obj
上),则将该方法放在构造函数' s {{1}上通过分配var obj = new Person()
(不共享)上的属性,将对象(共享)或方法分配给构造函数中的对象。
如果您希望方法在构造函数本身上可用,那么某些内置JavaScript方法(如prototype
或this
)的方式将其分配给构造:
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 Person
在sayHello
创建的实例上可用,因为它们是从原型继承而来的,原型由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
扩展您的原型:在开发期间添加日志记录信息,并将这些多余的日志记录信息放入生产中。