假设我有以下功能:
var A = function() {
var label = "hello";
return {
getLabel: function() { return label; }
}
};
Run Code Online (Sandbox Code Playgroud)
之间有什么区别:
var a = A();
Run Code Online (Sandbox Code Playgroud)
和
var a = new A();
Run Code Online (Sandbox Code Playgroud)
?
注意:我不是在问这里JavaScript中的'new'关键字,而是它在这个特定示例中的行为方式.
注意:
正如答案所说,由于问题和我的评论中描述的一些问题,问题中提出的代码并没有真正实现继承(否则它会成为答案而不是问题......).它可以像预期的那样继承假(甚至不是原型).
摘要
简而言之,使它类似于我们编写一般的OO语言而不是javascript,但保持继承是正确的.
故事
的Object.create是实现原型继承的好方法,但它是一个有点混乱,以一个类型的大脑和新的球迷.
我们可以通过各种方式编写javascript代码,就像我们使用伪经典模式编写其他OO语言一样.因为它是伪经典的,我们必须正确处理javascript的底层原型继承.
我想要找到的是一种可以在类声明上实现伪古典继承的方法.演示代码放在帖子的后面,它按预期工作,但是,有一些烦人的事情:
我无法摆脱return类声明或继承不起作用.
除了传入this类声明以使返回的闭包知道是什么,我没办法this.
我也想摆脱function (instance, _super) {,但还没有一个好主意.
不继承类的静态(自己的属性).
解决方案比现有框架更多的是一些语法糖,一个好的模式是适用的.
该_extends函数:
function _extends(baseType) {
return function (definition) {
var caller=arguments.callee.caller;
var instance=this;
if(!(instance instanceof baseType)) {
(caller.prototype=new baseType()).constructor=caller;
instance=new caller();
}
var _super=function () {
baseType.apply(instance, arguments);
};
definition(instance, _super);
return instance;
};
}
Run Code Online (Sandbox Code Playgroud)
本Abc类:
function Abc(key, …Run Code Online (Sandbox Code Playgroud) 很抱歉,如果之前已经回答过,但我对Javascript中创建自定义对象的选择数量感到有些不知所措.我不确定他们各自的优点或缺点,或者他们是否有所不同.
以下是我发现构建对象的一些不同方法:
1:新对象
person = new Object()
person.name = "Tim Scarfe"
person.height = "6Ft"
person.run = function() {
this.state = "running"
this.speed = "4ms^-1"
}
Run Code Online (Sandbox Code Playgroud)
2:文字表示法
timObject = {
property1 : "Hello",
property2 : "MmmMMm",
property3 : ["mmm", 2, 3, 6, "kkk"],
method1 : function(){alert("Method had been called" + this.property1)}
};
Run Code Online (Sandbox Code Playgroud)
3:功能
function AdBox() {
this.width = 200;
this.height = 60;
this.text = 'default ad text';
this.prototype.move = function() {
// code for move method goes here
} …Run Code Online (Sandbox Code Playgroud) 我有时看到人们这样做Function('alert("hi")'),有时他们这样做new Function('alert("hi")')
这两者有区别吗?
我有一个自包含的Backbone.View实现MainControllerView,可以处理自己(即,没有理由对它进行外部引用.).如果,在我的主要bootstrapper函数中,我会这样做:
$(function() {
new MainControllerView();
});
Run Code Online (Sandbox Code Playgroud)
JSLint/JSHint抱怨我使用"new for side effects".阅读此警告表示上述内容被视为有臭味的代码.替代方法是不使用new,只是将构造函数作为函数调用,或者将其赋值给变量.但是,MainControllerView()直接调用我的函数而不使用new主干代码中的引发错误,所以这显然不是一个选项.对我来说似乎完全错误,以下是更好的代码:
$(function() {
var instantGarbage = new MainControllerView();
});
Run Code Online (Sandbox Code Playgroud)
事实上,这会引发一个不同的JSLint警告"instantGarbage已定义但从未使用过".显然,如果我这样做,我就会感到危险,如果不这样做,我就会感到危险.那么,是否有一种不同的"正确"方式来处理这类事情?以某种方式创建即时垃圾变量是"更好的代码"替代方案吗?Backbone.js是否以非Crockford批准的方式利用"new"关键字?或者这只是"规则"的例外之一?
我观看了John Resig 在JavaScript库设计演示中的最佳实践 ; 一张幻灯片建议"调整"对象构造函数,以便实例化它自己.
function jQuery(str, con) {
if (window === this) {
return new jQuery(str, con);
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
new jQuery("#foo")随之而来的,变成了jQuery("#foo").
我认为这很有趣,但我没有在我自己的代码中编写类似的构造函数.
过了一会儿,我在这里看了一篇文章.(对不起,我不记得哪个或者我提供了一个链接.我会更新问题,如果我能再次找到它.)其中一条评论说这样做是不好的做法躲避new程序员,但没有详细说明.
我的问题是,上述一般认为好,坏,或无动于衷,为什么?
我更喜欢为我的代码使用函数OOP样式(类似于模块模式),因为它有助于我避免使用"new"关键字以及回调中"this"关键字范围的所有问题.
但我遇到了一些小问题.我想使用以下代码创建一个类.
namespace.myClass = function(){
var self = {},
somePrivateVar1;
// initialization code that would call
// private or public methods
privateMethod();
self.publicMethod(); // sorry, error here
function privateMethod(){}
self.publicMethod = function(){};
return self;
}
Run Code Online (Sandbox Code Playgroud)
问题是我无法从初始化代码中调用公共方法,因为这些函数尚未定义.显而易见的解决方案是创建一个init方法,并在"return self"行之前调用它.但也许你知道一个更优雅的解决方案?
另外,你通常如何使用这种模式处理继承?我使用以下代码,但我想听听您的想法和建议.
namespace.myClass2 = function(){
var self = namespace.parentClass(),
somePrivateVar1;
var superMethod = self.someMethod;
self.someMethod = function(){
// example shows how to overwrite parent methods
superMethod();
};
return self;
}
Run Code Online (Sandbox Code Playgroud)
编辑.对于那些询问选择这种OOP风格的原因的人,您可以查看以下问题:
据我所知,在JavaScript(Gecko变体)中:
var a = new A();
Run Code Online (Sandbox Code Playgroud)
是这样的语法糖:
var a = {};
a.__proto__ = A.prototype;
A.call(a);
Run Code Online (Sandbox Code Playgroud)
因此,A()(相当于A.call()?)和新的A()应该产生两个不同的结果,如下所示:
>>> new Date()
Fri Nov 19 2010 01:44:22 GMT+0100 (CET) {}
>>> typeof new Date()
"object"
>>> Date()
"Fri Nov 19 2010 01:44:42 GMT+0100 (CET)"
>>> typeof Date()
"string"
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.
但是,核心对象的Function行为有所不同:
>>> Function('return 123;')
anonymous()
>>> typeof Function('return 123;')
"function"
>>> Function('return 123;')()
123
>>> new Function('return 123;')
anonymous()
>>> typeof new Function('return 123;')
"function"
>>> …Run Code Online (Sandbox Code Playgroud) 我正在阅读这个链接http://addyosmani.com/largescalejavascript/#modpattern
并看到以下示例.
var basketModule = (function() {
var basket = []; //private
return { //exposed to public
addItem: function(values) {
basket.push(values);
},
getItemCount: function() {
return basket.length;
},
getTotal: function(){
var q = this.getItemCount(),p=0;
while(q--){
p+= basket[q].price;
}
return p;
}
}
}());
basketModule.addItem({item:'bread',price:0.5});
basketModule.addItem({item:'butter',price:0.3});
console.log(basketModule.getItemCount());
console.log(basketModule.getTotal());
Run Code Online (Sandbox Code Playgroud)
它的统计数据"模块模式是一种流行的设计模式,它使用闭包来封装'隐私',状态和组织"这与下面的编写有何不同?不能通过功能范围简单地执行隐私吗?
var basketModule = function() {
var basket = []; //private
this.addItem = function(values) {
basket.push(values);
}
this.getItemCount = function() {
return basket.length;
}
this.getTotal = function(){
var q = this.getItemCount(),p=0;
while(q--){ …Run Code Online (Sandbox Code Playgroud) 这两个原型继承实现之间有什么区别,并且考虑到我们正在使用2个不同的"原型"(仅在函数和内部原型上的原型属性),以及这些实现在原型链查找中有何不同?另外,第一个实现(使用prototype属性)是否依赖于我们对new运算符的使用?
分配给函数的prototype属性并使用new运算符:
function foo() {}
foo.prototype.output = function(){
console.log('inherits from Function.prototype property');
};
bar = new foo();
bar.output();
Run Code Online (Sandbox Code Playgroud)
将函数存储在对象文字中并使用该Object.create()方法:
var foo = {
output: function(){
console.log('inherits from the internal prototype');
}
};
var bar = Object.create(foo);
bar.output();
Run Code Online (Sandbox Code Playgroud) javascript ×10
prototype ×3
inheritance ×2
oop ×2
backbone.js ×1
class ×1
coding-style ×1
constructor ×1
function ×1
jslint ×1
module ×1
new-operator ×1
object ×1
types ×1