问题描述
我只是在学习Javascript,我想知道,正在使用原型声明,如下所示:
I am just learning Javascript and I was wondering, is using the prototype declaration, like this:
function TSomeObj()
{
this.name="my object";
}
TSomeObj.prototype.showname = function() {
alert(this.name);
}
基本上像这样做:
function TSomeObj()
{
this.name="my object";
this.showname = function() {
alert(this.name);
}
}
当我转储对象的属性时,我得到相同的结果:
When I dump the object's properties I get the same result:
TSomeObj (inline version) =
{
'name': 'my object',
'test': function
}
TSomeObj (prototype declaration) =
{
'name': 'my object',
'test': function
}
使用原型声明有什么好处?除了更少的混乱和更有序的源代码。
What exactly is the benefit of using prototype declarations? Except less cluttering and more orderly sourcecode perhaps.
更新:我或许应该更明确地说它是最终的结果我很好奇关于。最终结果是相同的(即在对象原型中都注册了一个新函数) - 但它们的方式却截然不同。感谢您的所有回复和信息!
Update: I should perhaps have made it more clear that it was the final result i was curious about. The end result is ofcourse the same (i.e both register a new function in the object prototype) - but the way they do it is wildly different. Thank you for all replies and info!
推荐答案
我最初回答错误的问题。以下是您实际问的问题的答案。我会留下我的其他笔记以防它们对某人有帮助。
I initially answered the wrong question. Here is the answer to your actually-asked question. I'll leave my other notes in just in case they're helpful to someone.
通过将属性添加到构造函数中的对象.prop
与通过 Object.prototype.prop
进行外部不同。
Adding properties to an object in the constructor function through this.prop
is different than doing so outside through Object.prototype.prop
.
-
最重要的区别是当你向一个函数的原型添加一个属性并从中实例化一个新对象时,通过加强继承链而在新对象中访问该属性。直接在物体上。
The most important difference is that when you add a property to the prototype of a function and instantiate a new object from it, that property is accessed in the new object by stepping up the inheritance chain rather than it being directly on the object.
var baseobj = {};
function ObjType1() {
this.prop = 2;
}
function ObjType2() {}
ObjType1.prototype = baseobj;
ObjType2.prototype = baseobj; // these now have the *same* prototype object.
ObjType1.prototype.prop = 1;
// identical to `baseobj.prop = 1` -- we're modifying the prototype
var a = new ObjType1(),
b = new ObjType2();
//a.hasOwnProperty('prop') : true
//b.hasOwnProperty('prop') : false -- it has no local property "prop"
//a: { prop = 2 }, b : { prop = 1 } -- b's "prop" comes from the inheritance chain
baseobj.prop = 3;
//b's value changed because we changed the prototype
//a: { prop = 2 }, b : { prop = 3 }
delete a.prop;
//a is now reflecting the prototype's "prop" instead of its own:
//a: { prop = 3 }, b : { prop = 3 }
第二个区别是,当代码执行时,向原型添加属性会发生一次,但会在构造函数中向对象添加属性每次创建新对象时。这意味着使用原型可以更好地执行并使用更少的内存,因为在叶子/邻近对象上设置相同的属性之前不需要新的存储。
A second difference is that adding properties to a prototype occurs once when that code executes, but adding properties to the object inside the constructor occurs each time a new object is created. This means using the prototype performs better and uses less memory, because no new storage is required until you set that same property on the leaf/proximate object.
另一个区别在于内部添加的函数可以访问私有变量和函数(在构造函数中使用 var
声明的那些),而基于原型或外部添加的函数不能,因为它们的范围错误:
Another difference is that internally-added functions have access to private variables and functions (those declared in the constructor with var
), and prototype-based or externally-added functions do not, simply because they have the wrong scope:
function Obj(initialx, initialy) {
var x = initialx,
y = initialy;
this.getX = function() {
return x;
}
var twoX = function() { // identical to `function twoX() { ... }`
return x * 2;
}
this.getTwoX = function() {
return twoX();
}
}
Obj.prototype.getY = function() {
return y; // fails, even if you try `this.y`
}
Obj.prototype.twoY = function() {
return y * 2; // fails
}
Obj.prototype.getTwoY = function() {
return twoY(); // fails
}
var obj = new Obj();
// obj.y : fails, you can't access "y", it is internal
// obj.twoX() : fails, you can't access "twoX", it is internal
// obj.getTwoX() : works, it is "public" but has access to the twoX function
关于javascript对象,函数和继承的一般说明
-
javascript中的所有非标量变量都是对象。 (并且一些明显的非对象类型在使用方法时进行装箱,例如布尔(Booleans))。它们都有点像哈希/字典,因为它们具有可以分配给它们的无限(?)个键/值对。
All non-scalar variables in javascript are objects. (And some apparent non-object types undergo boxing when a method is used on them such as Booleans). They all act somewhat like a hash/dictionary in that they have an unlimited(?) number of key/value pairs that can be assigned to them.
每个对象有一个原型的继承链,它一直到基础对象。当您访问对象的属性时,如果该对象本身不存在该属性,则检查该对象的秘密原型,如果不存在,则检查该对象的原型,依此类推等等。有些浏览器通过属性 __ proto __
公开这个原型。常规对象没有 prototype
属性,因为此属性用于函数,用于存储将创建的任何新对象的原型的对象使用该函数作为它们的构造函数。
Each object has an inheritance chain of "prototypes" that go all the way up to the base object. When you access a property of an object, if that property doesn't exist on the object itself, then the secret prototype of that object is checked, and if not present then that object's prototype, so on and so forth all the way up. Some browsers expose this prototype through the property __proto__
. Regular objects don't have a prototype
property because this property is for functions, to store the object that will be the prototype of any new objects created using that function as their constructor.
javascript函数是一个对象的特例,除了具有一个对象的键/值对之外具有参数和一系列按顺序执行的语句。
A javascript function is a special case of an object, that in addition to having the key/value pairs of an object also has parameters and a series of statements that are executed in order.
每次调用一个函数对象时,它都与另一个从该函数内访问的对象配对。函数由关键字 this
组成。通常,这个
对象是该函数属性的对象。例如,''。replace()
将字符串文字装入 String
,然后在替换函数中, this 指的是那个对象。另一个例子是当一个函数附加到DOM元素(可能是按钮上的onclick函数),然后这个
引用DOM元素。您可以使用 apply
或 call $ c $手动动态选择配对的
此
对象c>。
Every time a function object is invoked it is paired with another object that is accessed from within the function by the keyword this
. Usually, the this
object is the one that the function is a property of. For example, ''.replace()
boxes the string literal to a String
, then inside the replace function, this refers to that object. another example is when a function is attached to a DOM element (perhaps an onclick function on a button), then this
refers to the DOM element. You can manually choose the paired this
object dynamically using apply
or call
.
当使用 new
关键字调用javascript函数时,如 var obj = new Obj()
,这会导致一件特别的事情发生。如果您没有专门返回任何内容,那么现在包含 Obj $的返回值,而不是
obj
c $ c> function,它包含在调用时与函数配对的 this object ,它将是一个新的空对象,其继承链中的第一个父对象设置为 Obj.prototype
(请记住,在某些浏览器中可通过 obj .__ proto __
访问)。调用的 Obj()
函数在运行时可以修改新对象的属性。然后返回该对象。
When a javascript function is invoked with the new
keyword as in var obj = new Obj()
, this causes a special thing to happen. If you don't specifically return anything, then instead of obj
now containing the return value of the Obj
function, it contains the this object that was paired with the function at invocation time, which will be a new empty object with the first parent in its inheritance chain set to Obj.prototype
(remember, accessible in some browsers via obj.__proto__
). The invoked Obj()
function, while running, can modify the properties of the new object. Then that object is returned.
您不必担心关键字构造函数
,只需说 obj.constructor
指向Obj函数(所以你可以找到创建它的东西),但你可能不需要使用它来大多数事情。
You don't have to worry much about the keyword constructor
, just suffice it to say that obj.constructor
points to the Obj function (so you can find the thing that created it), but you'll probably not need to use this for most things.
回到你的问题。要理解在构造函数中修改对象属性和修改其原型之间的区别,请尝试以下方法:
Back to your question. To understand the difference between modifying the properties of an object from within the constructor and modifying its prototype, try this:
var baseobj = {prop1: 'x'};
function TSomeObj() {
this.prop2 = 'y';
};
TSomeObj.prototype = baseobj;
var a = new TSomeObj();
//now dump the properties of `a`
a.prop1 = 'z';
baseobj.prop1 = 'w';
baseobj.prop2 = 'q';
//dump properties of `a` again
delete a.prop1;
//dump properties of `a` again
你会看到设置 a.prop1
实际上是在创建邻居对象的新属性,但它不会覆盖基础对象的prop1。当您从 a
中删除 prop1
时,您将获得继承的 prop1
我们改变了。此外,即使我们在之后添加了
prop2
,但是 a
仍然拥有该财产。这是因为javascript使用原型继承而不是经典继承。当您修改 TSomeObj
的原型时,您还修改了以前实例化的所有对象,因为它们正在从中继承它。
You'll see that setting a.prop1
is actually creating a new property of the proximate object, but it doesn't overwrite the base object's prop1. When you remove prop1
from a
then you get the inherited prop1
that we changed. Also, even though we added prop2
after a
was created, a
still has that property. This is because javascript uses prototype inheritance rather than classic inheritance. When you modify the prototype of TSomeObj
you also modify all its previously-instantiated objects because they are actively inheriting from it.
当您使用任何编程语言实例化一个类时,新对象将采用其构造函数类的属性(我们通常将其视为对象的同义词)。在大多数编程语言中,除了停止程序和更改类声明之外,您无法更改类或实例化对象的属性或方法。
When you instantiate a class in any programing language, the new object takes on the properties of its "constructor" class (which we usually think of as synonymous with the object). And in most programming languages, you can't change the properties or methods of the class or the instantiated object, except by stopping your program and changing the class declaration.
Javascript但是,允许您在运行时修改对象和classes的属性,并且还会修改该类型类的所有实例化对象,除非它们具有覆盖修改的属性。对象可以生成可以生成对象的对象,因此这可以在一直到Object类的链中工作。我把类放在引号中,因为实际上,Javascript中的所有内容都是一个对象,除了 new
关键字允许你制作外,它确实不是一个类。具有继承链的新对象为您连接,所以我们称它们为类,即使它们只是使用 new
关键字调用构造函数的结果。
Javascript, though, lets you modify the properties of objects and "classes" at run-time, and all instantiated objects of that type class are also modified unless they have their own properties that override the modification. Objects can beget objects which can beget objects, so this works in a chain all the way up to the Object class. I put "classes" in quotes because really, everything in Javascript is an object and there really isn't such a thing as a class, except that the new
keyword lets you make new objects with the inheritance chain hooked up for you, so we call them classes even though they're just the result of constructor functions being called with the new
keyword.
其他一些注释:函数有一个Function构造函数,对象有一个Object构造函数。 Function构造函数的原型是(惊讶,惊讶)Object。
Some other notes: functions have a Function constructor, objects have an Object constructor. The prototype of the Function constructor is (surprise, surprise) Object.
从没有运行构造函数的对象继承
在某些情况下,能够在没有运行构造函数的情况下创建新的对象实例非常有用。你可以继承类而不运行类的构造函数(就像手动执行 child .__ proto__ = parent
):
In some cases, it's useful to be able to create a new "instance of an object" without the constructor function running. You can inherit from a class without running the class's constructor function like so (almost like manually doing child.__proto__ = parent
):
function inheritFrom(Class) {
function F() {};
F.prototype = Class.prototype;
return new F();
}
这篇关于原型或内联,有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!