向函数对象添加属性与向对象原型添加属性之间的区别是什么。请参阅下面的代码。
var foo = function() { this.name = alert("test") };
foo.newProp = function() { ... };
var value = new foo();
// vs
foo.prototype.newProp = function() { ... }
var value = new foo();
我的困惑是当为每个代码运行此代码时会发生什么值,以及“这个”如何受到影响。
答案 0 :(得分:1)
首先,我们知道函数只是对象,因为我们可以将属性附加到它。这就是案例1中发生的事情。
我们只是将属性附加到function Foo
案例1
var Foo = function(){
this.name = "myname";
}
Foo.newProp = function(){};
可以简单地访问附加到函数的属性,作为访问对象属性的方式。
案例2
在这种情况下,相同的属性位于该函数的prototype
。使用此function Foo
创建任何对象时,默认情况下它将访问此函数。
使用该对象调用函数时,上下文this
将知道调用该函数的对象,this
指向调用它的对象。
Foo.prototype.newProp = function(){ console.log("function on prototype");}
var value = new Foo();
console.log(value);
同样在情况2中,由于我们正在向函数的原型添加属性,因此它们不是坐在使用该函数创建的对象上,而是放在该对象的proto上。查看下面显示的屏幕截图:
这意味着存在一个公共内存位置,访问该属性的每个对象都将指向该位置,因此它也具有内存效率。
您可以随时通过直接在对象上定义它来覆盖它来修改该属性:
value.newProp = function(){ console.log("modified property") };
现在,如果你调用这个函数,它将直接在对象上找到它并且不会沿着原型链从公共存储器位置访问它,即function Foo
的原型
答案 1 :(得分:1)
由于函数是对象,因此案例1只不过是向对象添加属性。案例2更有趣。请考虑以下代码:
function f (name) {
this.name = name;
}
f.prototype.sayHello = function () {
console.log("Hello I'm " + this.name + " !");
};
var x = new f("X");
var y = new f("Y");
<button type="button" onclick="x.sayHello()">x.sayHello()</button>
<button type="button" onclick="y.sayHello()">y.sayHello()</button>
请注意,此代码中没有x.sayHello = function () {...}
。想想它两次并问自己:
由于
x.sayHello
从未明确定义,阻止x.sayHello()
程序崩溃的基本机制是什么?
这是个问题。
幸运的是,没有什么神奇的,只有JavaScript内部处理。实际上,当您使用new
创建对象时,或者当您调用函数时,在场景后面会发生事件,其中涉及prototype
属性。
当您编写new f()
时,JavaScript引擎:
this
设置为新对象。f
。__proto__
的属性添加到新对象。__proto__
绑定到f.prototype
。当您编写x.sayHello()
时,JavaScript引擎:
x
。sayHello
,请转到第6步。x.__proto__
。sayHello
,请转到第6步。this
设置为x
。sayHello
。要强调的要点:
new
关键字时,JavaScript会创建一个原型链,即引擎执行以下任务:x.__proto__ = f.prototype
。x.sayHello()
时,如果JavaScript无法在sayHello
中找到x
,则会查看x.__proto__
f.prototype
。this
的值取决于上下文。例如,当您撰写x.sayHello()
时,this
为x
,当您撰写y.sayHello()
时,this
为y
,当您撰写new f()
时1}},this
是一个新对象。 More about this
。自定义实施:
function instanciate (f, args) {
var object = {};
f.apply(object, args);
object.__proto__ = f.prototype;
return object;
}
function execute (object, fName, args) {
var f = lookup(object, fName);
if (typeof f !== "function") {
throw "not a function";
} else {
f.apply(object, args);
}
}
function lookup (object, key) {
do {
if (object.hasOwnProperty(key)) {
return object[key];
} else {
object = object.__proto__;
}
}
while (object !== null);
}
function f (name) {
this.name = name;
}
f.prototype.sayHello = function () {
console.log("Hello I'm " + this.name + " !");
};
var x = instanciate(f, ["X"]);
var y = instanciate(f, ["Y"]);
<button
type="button"
onclick="execute(x, "sayHello")"
>execute(x, "sayHello")</button>
<button
type="button"
onclick="execute(y, "sayHello")"
>execute(y, "sayHello")</button>
全局对象并不特别:
f.prototype.__proto__ = window.__proto__;
window.__proto__ = f.prototype;
name = "John Doe";
sayHello(); // "Hello I'm John Doe !"
答案 2 :(得分:0)
foo.newProp = function(){...};?
这将定义函数(类)级别的函数。
您可以直接访问它而无需使用对象。
foo.newProp() // call it.
foo.prototype.newProp = function(){...};?
它在实例级别定义newProp
(object or class instance
)。
您需要使用new
定义对象,然后才能访问它。
var value = new foo();
value.newProp() // call it
通过使用原型定义函数,可以使所有已经+新定义的对象使用给定的函数