- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想知道创建具有属性和方法的 JavaScript 对象的最佳方法是什么。
我看过这个人使用 var self = this
的例子然后使用 self.
在所有功能中以确保范围始终正确。
然后我看到了使用 .prototype
的例子添加属性,而其他人则是内联的。
有人能给我一个带有一些属性和方法的 JavaScript 对象的正确例子吗?
最佳答案
在 JavaScript 中有两种实现类和实例的模型:原型(prototype)方式和闭包方式。两者都有优点和缺点,并且有很多扩展的变化。许多程序员和库有不同的方法和类处理实用程序函数来掩盖语言的一些丑陋部分。
结果是,在混合公司中,您将混杂元类,所有元类的行为都略有不同。更糟糕的是,大多数 JavaScript 教程 Material 都很糟糕,并且提供了某种中间妥协以涵盖所有基础,让您感到非常困惑。 (可能作者也很困惑。JavaScript 的对象模型与大多数编程语言非常不同,并且在许多地方直接设计得很糟糕。)
让我们从 开始原型(prototype)方式 .这是您可以获得的最原生的 JavaScript:代码开销最少,并且 instanceof 将处理此类对象的实例。
function Shape(x, y) {
this.x= x;
this.y= y;
}
new Shape
创建的实例添加方法将它们写到
prototype
查找此构造函数:
Shape.prototype.toString= function() {
return 'Shape at '+this.x+', '+this.y;
};
prototype
属性(property):
function Circle(x, y, r) {
Shape.call(this, x, y); // invoke the base class's constructor function to take co-ords
this.r= r;
}
Circle.prototype= new Shape();
Circle.prototype.toString= function() {
return 'Circular '+Shape.prototype.toString.call(this)+' with radius '+this.r;
}
new Shape()
很难看:即使没有实际的 Shape 被创建,我们也在实例化基类。它恰好适用于这种简单的情况,因为 JavaScript 是如此草率:它允许传入零个参数,在这种情况下
x
和
y
成为
undefined
并分配给原型(prototype)的
this.x
和
this.y
.如果构造函数正在做任何更复杂的事情,它就会一败涂地。
function subclassOf(base) {
_subclassOf.prototype= base.prototype;
return new _subclassOf();
}
function _subclassOf() {};
function Circle(x, y, r) {
Shape.call(this, x, y);
this.r= r;
}
Circle.prototype= subclassOf(Shape);
new Shape()
错误。我们现在有一组可接受的原语来构建类。
Function.prototype.subclass= function(base) {
var c= Function.prototype.subclass.nonconstructor;
c.prototype= base.prototype;
this.prototype= new c();
};
Function.prototype.subclass.nonconstructor= function() {};
...
function Circle(x, y, r) {
Shape.call(this, x, y);
this.r= r;
}
Circle.subclass(Shape);
apply
稍微自动化,但你仍然必须写出:
function Point() {
Shape.apply(this, arguments);
}
Point.subclass(Shape);
function Shape() { this._init.apply(this, arguments); }
Shape.prototype._init= function(x, y) {
this.x= x;
this.y= y;
};
function Point() { this._init.apply(this, arguments); }
Point.subclass(Shape);
// no need to write new initialiser for Point!
Function.prototype.subclass
,转过来让基类的函数吐出子类:
Function.prototype.makeSubclass= function() {
function Class() {
if ('_init' in this)
this._init.apply(this, arguments);
}
Function.prototype.makeSubclass.nonconstructor.prototype= this.prototype;
Class.prototype= new Function.prototype.makeSubclass.nonconstructor();
return Class;
};
Function.prototype.makeSubclass.nonconstructor= function() {};
...
Shape= Object.makeSubclass();
Shape.prototype._init= function(x, y) {
this.x= x;
this.y= y;
};
Point= Shape.makeSubclass();
Circle= Shape.makeSubclass();
Circle.prototype._init= function(x, y, r) {
Shape.prototype._init.call(this, x, y);
this.r= r;
};
makeSubclass
获取并记住类名并提供默认值
toString
使用它。也许你想让构造函数检测到它何时被意外调用而没有
new
运算符(否则通常会导致非常烦人的调试):
Function.prototype.makeSubclass= function() {
function Class() {
if (!(this instanceof Class))
throw('Constructor called without "new"');
...
makeSubclass
将它们添加到原型(prototype)中,这样您就不必编写
Class.prototype...
相当多。许多类系统都这样做,例如:
Circle= Shape.makeSubclass({
_init: function(x, y, z) {
Shape.prototype._init.call(this, x, y);
this.r= r;
},
...
});
function Shape(x, y) {
var that= this;
this.x= x;
this.y= y;
this.toString= function() {
return 'Shape at '+that.x+', '+that.y;
};
}
function Circle(x, y, r) {
var that= this;
Shape.call(this, x, y);
this.r= r;
var _baseToString= this.toString;
this.toString= function() {
return 'Circular '+_baseToString(that)+' with radius '+that.r;
};
};
var mycircle= new Circle();
Shape
的每个实例将拥有自己的
toString
副本方法(以及我们添加的任何其他方法或其他类成员)。
instanceof
运算符(operator)将无法工作;如果需要,您必须提供自己的类嗅探机制。虽然您可以使用与原型(prototype)继承类似的方式来处理原型(prototype)对象,但这有点棘手,而且仅仅获得
instanceof
并不值得。在职的。]
this
在方法调用中,结果是如果您将方法与其所有者分离:
var ts= mycircle.toString;
alert(ts());
this
方法内部不会是预期的 Circle 实例(它实际上是全局
window
对象,导致广泛的调试问题)。实际上,这通常发生在采用方法并将其分配给
setTimeout
时。 ,
onclick
或
EventListener
一般来说。
setTimeout(function() {
mycircle.move(1, 1);
}, 1000);
function.bind()
来做到这一点。 :
setTimeout(mycircle.move.bind(mycircle, 1, 1), 1000);
that
或
self
,但我个人建议不要使用后者,因为
self
已经有另一个不同的JavaScript 中的意思)。你没有得到参数
1, 1
在上面的代码片段中是免费的,所以你仍然需要另一个闭包或
bind()
如果你需要这样做。
this
完全,创建一个新的
that
并返回它而不是使用
new
运算符(operator):
function Shape(x, y) {
var that= {};
that.x= x;
that.y= y;
that.toString= function() {
return 'Shape at '+that.x+', '+that.y;
};
return that;
}
function Circle(x, y, r) {
var that= Shape(x, y);
that.r= r;
var _baseToString= that.toString;
that.toString= function() {
return 'Circular '+_baseToString(that)+' with radius '+r;
};
return that;
};
var mycircle= Circle(); // you can include `new` if you want but it won't do anything
关于javascript - 如何 "properly"在 JavaScript 中创建自定义对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1595611/
我的一位教授给了我们一些考试练习题,其中一个问题类似于下面(伪代码): a.setColor(blue); b.setColor(red); a = b; b.setColor(purple); b
我似乎经常使用这个测试 if( object && object !== "null" && object !== "undefined" ){ doSomething(); } 在对象上,我
C# Object/object 是值类型还是引用类型? 我检查过它们可以保留引用,但是这个引用不能用于更改对象。 using System; class MyClass { public s
我在通过 AJAX 发送 json 时遇到问题。 var data = [{"name": "Will", "surname": "Smith", "age": "40"},{"name": "Wil
当我尝试访问我的 View 中的对象 {{result}} 时(我从 Express js 服务器发送该对象),它只显示 [object][object]有谁知道如何获取 JSON 格式的值吗? 这是
我有不同类型的数据(可能是字符串、整数......)。这是一个简单的例子: public static void main(String[] args) { before("one"); }
嗨,我是 json 和 javascript 的新手。 我在这个网站找到了使用json数据作为表格的方法。 我很好奇为什么当我尝试使用 json 数据作为表时,我得到 [Object,Object]
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我听别人说 null == object 比 object == null check 例如: void m1(Object obj ) { if(null == obj) // Is thi
Match 对象 提供了对正则表达式匹配的只读属性的访问。 说明 Match 对象只能通过 RegExp 对象的 Execute 方法来创建,该方法实际上返回了 Match 对象的集合。所有的
Class 对象 使用 Class 语句创建的对象。提供了对类的各种事件的访问。 说明 不允许显式地将一个变量声明为 Class 类型。在 VBScript 的上下文中,“类对象”一词指的是用
Folder 对象 提供对文件夹所有属性的访问。 说明 以下代码举例说明如何获得 Folder 对象并查看它的属性: Function ShowDateCreated(f
File 对象 提供对文件的所有属性的访问。 说明 以下代码举例说明如何获得一个 File 对象并查看它的属性: Function ShowDateCreated(fil
Drive 对象 提供对磁盘驱动器或网络共享的属性的访问。 说明 以下代码举例说明如何使用 Drive 对象访问驱动器的属性: Function ShowFreeSpac
FileSystemObject 对象 提供对计算机文件系统的访问。 说明 以下代码举例说明如何使用 FileSystemObject 对象返回一个 TextStream 对象,此对象可以被读
我是 javascript OOP 的新手,我认为这是一个相对基本的问题,但我无法通过搜索网络找到任何帮助。我是否遗漏了什么,或者我只是以错误的方式解决了这个问题? 这是我的示例代码: functio
我可以很容易地创造出很多不同的对象。例如像这样: var myObject = { myFunction: function () { return ""; } };
function Person(fname, lname) { this.fname = fname, this.lname = lname, this.getName = function()
任何人都可以向我解释为什么下面的代码给出 (object, Object) 吗? (console.log(dope) 给出了它应该的内容,但在 JSON.stringify 和 JSON.parse
我正在尝试完成散点图 exercise来自免费代码营。然而,我现在只自己学习了 d3 几个小时,在遵循 lynda.com 的教程后,我一直在尝试确定如何在工具提示中显示特定数据。 This code
我是一名优秀的程序员,十分优秀!