通常一个构造函数是这样子的,它带有一个area的原型方法,在构造函数中传入长、宽并计算面积。
var Shape = function(width, height) {
this.width = width;
this.height = height;
};
Shape.prototype.area = function() {
return this.width * this.height
};
var shape = new Shape(20, 30);
shape.area();
> 600
输出很完美,这也是经典JavaScript实现继承的方法,通过prototype添加对另外一个对象的引用。
不过一部分JavaScript程序是非常讨厌new关键字的,这个关键字有太浓烈的Java烙印了,而且掩盖了JavaScript基于原型的本质,降低了程序员使用JS语言的效率,因此你想把它省了,看看结果?
var shape = Shape(20, 30);
shape.area();
> TypeError: Cannot read property 'area' of undefined
道理再简单不过了,你只不过是执行了一个函数,但是这个函数并没有返回值,所以shape必然是undefined,看来new关键作用之一跟Java是一样的,就是实例化此对象并返回这个对象本身。所以你又试改写了一下函数:
var Shape = function(width, height) {
var self = this;
self.area = function() {
return width * height;
}
return self;
};
var shape = Shape(20, 30);
shape.area();
> 600
不错,It works!也不用实例化Shape了,看上去一切正常,代码看上去更简单了,隐藏了不必要的属性,不过似乎你没有意识到你设计了一个潜在的更大的坑,尝试在console中打印这些:
area
> function () { return self.width * self.height; }
为什么are变成了全局变量?你不死心,又在window里打印
结果还一样,其实这一现象在"Javascript: The Good Parts"一书中有很好的解析:
window.area
> function () {
return width * height;
}
结果还一样,其实这一现象在"Javascript: The Good Parts"一书中有很好的解析:
If you forget to include the new prefix when calling a constructor function, then this will not be bound to the new object. Sadly, this will be bound to the global object, so instead of augmenting your new object, you will be clobbering global variables. That is really bad. There is no compile warning, and there is no runtime warning. (page 49)
如果你在一个构造函数中忘了加new,那么这个新对象就不会绑定到新的实例上,不幸的是,它会绑定到全局对象上,你就会影响全局变量。这是非常糟糕的。没有编译警告,并且没有运行时的警告。(第49页)
看来在function函数内使用this绑定公开属性是非常危险的,因为你不确定会不会有人忘写了一个new,或者故意不加一个new,也许这就是为什么基于function的构造函数现在用得越来越少的原因吧,其实解决的办法非常简单,只需更改一处。
var Shape = function(width, height) {
var self = {};
self.area = function() {
return width * height;
}
return self;
};
var shape = Shape(20, 30);
shape.area(); >600
@iSayme #0
呵,这种解决方案比较正统
別扯淡了. 去看看 minimalist approach.
http://www.ruanyifeng.com/blog/2012/07/three_ways_to_define_a_javascript_class.html
单例以后,如何实现继承?个人觉得new挺好,有效的隔绝了作用域。
这个得看个人喜好,基于Object就基本上需要使用Object.create来继承,不过需要单独写一个方法来进行构造函数的工作,如:
基于Function与基于Object皆可,不过个人最近比较倾向于基于Object的。而且构造函数被提取出来以后,一旦构造规则发生改变,再写一个构造函数即可,不会对原有功能造成影响。
f
可以用原型继承,var a = Object.create(obj);
这里提出一个简单的方法,但是稍微复杂或者要带参建议使用new关键字构造方法,如果单单是工具,那么直接封装到一个全局变量就行了。
不可修改,不可删除的评论是不是不科学?
范文芳 范德萨都是第三方发到付
1
..
www.aijquery.cn 爱jquery 很好的网站
标题111
在这里1111111111111111111输入代码
111111111111111*强调11111111111111111**加粗文本**文本*1#