我编写了以下代码来理解JavaScript中的实现和闭包类。
function Person(name) {
this.Name = name;
console.log("Person Fired!!");
(function EchoMyName(temp) {
console.log("EchoMyName - " + temp);
}("Self Called"));
EchoMyName("Called by Person!");
}
Person.prototype.CallMe = function(){
console.log("Call Me Fired!");
EchoMyName("Called by CallMe!");
}
在我实例化Person
时,我得到以下输出 -
Person Fired!!
EchoMyName - Self Called
ReferenceError: EchoMyName is not defined
但它就在那里,我在打电话之前定义了它?为什么会出错?
此外,当我修改代码以删除以前的错误并在某人身上调用CallMe
时,似乎它无法访问EchoMyName
function Person(name) {
this.Name = name;
console.log("Person Fired!!");
function EchoMyName(temp) {
console.log("EchoMyName - " + temp);
};
}
Person.prototype.CallMe = function(){
console.log("Call Me Fired!");
EchoMyName("Called by CallMe!");
}
拨打:
new Person().CallMe();
输出
Person Fired!!
Call Me Fired!
ReferenceError: EchoMyName is not defined
更新#1
感谢所有答案。我在Douglas Crockford的网站上找到了这个链接: http://javascript.crockford.com/private.html
它提供了对JavaScript中隐藏信息的非常清晰的理解。
答案 0 :(得分:3)
由于以下代码而发生引用错误:EchoMyName("Called by Person!");
EchoMyName
是一个自调用函数,位于名为Person
的JavaScript构造函数的范围内。一旦它被自我调用,它就不再存在。如果我们使用另一种编程语言,我们可以对匿名对象进行类比。
在JavaScript中,函数实际上是对象。声明函数时,您正在创建Function对象的实例。
以下是一些声明功能的不同方法。
//function statement
function x (a, b) { return a + b; }
//function expression, this will store an anonymous function into a variable
var y = function (a, b) { return a + b; };
//Function constructor
var z = new Function ("a", "b", "return a + b;"); // avoid this form, it will prevent certain optimizations from the browser's JS engine because of the strings (this is just an example)
在JavaScript函数中声明变量或函数时,它仅限于函数的范围。构造函数也是如此。
您需要声明一个函数表达式并将其存储在Person
构造函数的属性中。
下面的小例子。
function Person(name) {
this.Name = name;
console.log("1 Person Fired!!");
// notice that function is stored in this.EchoMyName
this.EchoMyName = function(temp) {
console.log("2 EchoMyName - " + temp);
};
console.log("3 Still in Person!")
}
Person p = new Person("Bob");
p.EchoMyName("Hello World!");
输出:
1 Person Fired!!
3 Still in Person!
2 EchoMyName - Hello World!
在JavaScript中,没有像许多其他面向对象语言(C ++,C#,Java)那样的传统继承。你所拥有的是对象链。
如果我们在示例中使用您的代码,Person构造函数将在一个名为 prototype 的属性中存储一个阴影对象。 Person的每个实例都将引用相同的原型。此外,原型的原型是Object。
我邀请您阅读Mozilla开发者网络中的文章Inheritance and the prototype chain以获取更多信息。
答案 1 :(得分:2)
(function EchoMyName(temp) {
console.log("EchoMyName - " + temp);
}("Self Called"));
这是函数表达式,而不是函数定义;名称EchoMyName
仅指函数本身内部的函数,因此以后不能使用它。 (在IE的JScript中除外,这是错误的。)
你的第二个问题源于这样一个事实:你所拥有的不是一个阶级;这是一个功能。可以在JavaScript中的函数内声明一个函数,并且它将作用于该函数,就像常规变量一样(但是可以在函数的任何位置使用它)。原型只是一个对象,并且无法访问构造函数的局部变量。
总结一下,在ECMAScript 5中:
catch
this
,如果他们需要目标的东西(如果他们不需要,为什么他们在原型上?)答案 2 :(得分:1)
但它就在那里,我在打电话之前定义了它?为什么会出错?
不同之处在于如何评估function
定义。
在第1段中,由于围绕它的括号,EchoMyName
是function expression。允许立即调用它们,但只能在它们自己的正文中引用它们。
在第二天,EchoMyName
取而代之的是function declaration。这些都受hoisting约束,允许他们在自己的身体之外引用他们的名字。
似乎无法访问EchoMyName
这是因为EchoMyName
绑定到Person
内的范围。除此之外,EchoMyName
不存在。
您需要通过EchoMyName
或this
将Person.prototype
附加到实例,以便CallMe
可以访问它:
this.EchoMyName = function EchoMyName(temp) {
console.log("EchoMyName - " + temp);
};
Person.prototype.EchoMyName = function EchoMyName(temp) {
console.log("EchoMyName - " + temp);
};
Person.prototype.CallMe = function(){
console.log("Call Me Fired!");
this.EchoMyName("Called by CallMe!");
};
或者,如果您希望保留EchoMyName
作用域以使其无法被其他代码调用,则还需要在同一作用域CallMe
内定义function
。但是,这不一定是Person
:
var Person = (function () {
function Person(name) {
this.Name = name;
console.log("Person Fired!!");
}
function EchoMyName(temp) {
console.log("EchoMyName - " + temp);
}
Person.prototype.CallMe = function () {
console.log("Call Me Fired!");
EchoMyName("Called by CallMe!");
};
return Person;
})();