在类的构建过程中,对于一个特定值的访问既可以使用属性也可以使用方法
例子:
//实现
//Point类,表示平面上的一个点
function Point(x,y){
this.x = x;
this.y = y;
//距原点的距离,使用属性来实现
Object.defineProperty(this,"distance",{
get: function(){
return Math.sqrt(this.x*this.x + this.y*this.y);
}
});
}
//距原点的距离,使用方法来实现
Point.prototype.getDistance = function(){
return Math.sqrt(this.x*this.x + this.y*this.y);
}
//访问
var a = new Point(3,5);
//使用属性访问
Console.log(a.distance);
//使用方法访问
Console.log(a.getDistance());
问题:
在哪些情况下应使用属性,在哪些情况下应使用方法?
使用属性和使用方法各有哪些优缺点?
有哪些介绍相关内容的文章或书籍?
PHP中文网2017-04-11 12:47:18
你这个问题其中在 Javaer 中已经讨论了很久了。Java Bean 为什么一定要用 getter 和 setter,讨论的就是这个问题。
我这里只是简单的说一下,你可以自己去百度相关的资料。
对于 Java 来说,就是属性和方法,通过 getXxxx() 和 setXxxx() 这两种方法来获取或设置属性的值。
不过对于 js 来说,可以通过 Object.defineProperty 来定义属性,这个属性和原来直接 this.xxxx
的这个属性应该有所区别,所以通常会把 this.xxxxx
这个称为字段 (Field),而把 Object.defineProperty
定义的那个称为属性。由于 JS 有属性,所以不需要(但可以)申明 getter 和 setter 方法,反正作用是一样的。
现在从 JS 的角度来说,所有会提到“字段”和“属性”。
相比字段,属性有几个作用,其一就是保护字段。比如我定义了一个字段,这个字段的值只能在内部修改,而不能被外部调用者修改,那只需要定义对应的只读属性,也就是只有 getter 没有 setter 的属性即可。当然这在 JS 里还有点困难,因为 JS 没有实现私有成员,关于 JS 成员私有化的问题,可以参考 ES5 中模拟 ES6 的 Symbol 实现私有成员。由于字段被私有化,对应的属性又只提供了 getter,所以外部调用只能通过属性的 getter 获取字段值,而不能修改它,达到保护的目的。
第二个作用是重载处理,这在 JS 里体现也不明显,因为 ES5 的继承实现确实有点麻烦。不过 ES6 在语法上已经支持了。具体点说,就是父类定义了一个属性,子类重载这个属性,改变了父类存取属性默认行为。比如说,父类的 name
属性对值没有限制,但是由于某种原因,需要父类类似的功能,但 name
不能为空,那可以从该父类继承,重载其 name
属性,在赋空值的自动修正,或报错。
class A {
get name() {
return this._name;
}
set name(name) {
this._name = name;
}
}
class B extends A {
get name() {
return super.name;
}
set name(name) {
super.name = name || "Anonymous";
}
}
const b = new B();
b.name = "";
console.log(b.name);
总的来说,字段一般作为内部保存数据用,不对外。如果需要对外,则通过属性来实现。这种设计模式对扩展很有好处。JavaScript 在这方面应用不是很多,如果你想参考,可以看看 C# 的属性和 Java 的 getter/setter 方法。
阿神2017-04-11 12:47:18
所谓的属性和方法只是叫法上的不同。方法可以是属性,属性也可以是方法。如下:
function Point(x,y){
this.x = x;
this.y = y;
this.z = function(){console.log(this.x);};
//距原点的距离,使用属性来实现
Object.defineProperty(this,"distance",{
get: function(){
return Math.sqrt(this.x*this.x + this.y*this.y);
}
});
}
//距原点的距离,使用方法来实现
Point.prototype.getDistance = function(){
return Math.sqrt(this.x*this.x + this.y*this.y);
}
//访问
var p = new Point(3,5);
'x' in p //true
'getDistance' in p //true
p.hasOwnProperty('getDistance'); //false这是这个方法的特性,不遍历原型链
p.hasOwnProperty('distance'); //true
p.hasOwnProperty('y'); //true
p.hasOwnProperty('z'); //true
只不过按前辈的经验来分,属性一般是一个值,可以获取,可以改变。而方法一般是一段可以执行的代码,可以操作属性值。外部调用时属性直接使用,方法需要(),予以执行。