EDITED FOR CLARIFICATION
在我说任何事之前,请参阅How Classical Object-Oriented Programming Translates to Javascript。这是非常重要的理解。现在,这就是说,我会继续:)
JavaScript有一个不幸的特点,你必须非常了解运行时环境,以了解为什么某些语法选择超过另一个表达相同事情(理论上)。 JavaScript运行环境的一个主要注意事项是,无意中将事情引入全局空间是非常容易的。这里有两个快速的例子(这些例子假设你没有任何其他代码编写):
/*
* Example 1
* This example uses 'object literal notation'.
* A link to an article about this is below the example.
* This example shows how easy it is to get into the global space just by
* not declaring variables properly.
*/
var myObj = {
myMethod: function() {
test = 'test'; // oops! now the variable test is in the global
// function space :(
// to avoid this, use var test = 'test'; to keep
// test in the scope of myMethod
}
};
阅读object literal notation。
/*
* Example 2
* This example shows how the infamous 'this' can be misused to accidentally
* get into the global space.
*/
var myConstructor = function() {
this.test = 'test';
};
var myObj1 = new myConstructor(); // 'this' will by 'myObj1'
var myObj2 = myConstructor(); // 'this' will by the global object :(
要了解为什么实例2成立,请参阅this。
避免所有这些问题的方法之一就是遵循控制访问全局范围的好模式。正如其中一些答案指出的那样,您可以将StackExchange
对象视为用于命名空间的目的,但实际上,它最常用于避免上述示例中列出的问题,还可以防止名称提升等情况。此外,如果您在使用闭包范围时非常聪明(利用javascript中的所有范围都绑定到函数以及在函数中定义函数的事实),则可以使此“命名空间”对象更像传统的其他经典OOP语言对象javascript是一流的数据对象)。此外,由于全球空间非常危险,最好是“成为一名优秀的DOM公民”,并且只在全球空间创建一个封装所有逻辑和数据的对象。
乔尔和杰夫可能实际上设置闭合范围来做信息隐藏JavaScript的方式。以下仅仅是一个例子:
StackExchange = (function() { // give StackExchange it's own scope to prevent
// name hoisting and also to allow for private
// data
var version = '1.0.0'; // version only seen inside function scope
return { // return an object that will become 'StackExchange' and whose
// methods have access to this function's scope (closure)
debug: (function() {
// set up logging function that will be determined based on
// 'someCondition' (not defined in this code)
var loggingFn = (someCondition) : console.log ? alert;
return { // return obj with access to this function scope
log: function(strToLog) {
loggingFn.call(this, strToLog);
}
};
})(), // immediately execute to make object with 'debug' scope access
getVersion: function() {
return version; // this function has access to StackExchange
// scope; therefore, version will be available
}
};
})(); // immediately execute to make object with 'StackExchange' scope access
欲了解更多信息,请参阅name hoisting和scoping。此外,请阅读Prototypical Inheritance in Javascript以了解用于避免全局范围问题的模式。
感谢例如,我很困惑,我的PHP经验我熟悉“命名空间 - >类 - >功能或财产”我可以将这一点与此有关,但我有很多东西要学。像语法这样的东西,我已经看到了JavaScript函数的定义和调用了几种不同的方式,就好像没有标准语法(我确定有,只是我的基本JS知识让我看到) – JasonDavis
我很好奇,可以深入多层次?而'StackExchange = {}'为什么'debug:{}'有'':“'而另一个没有? – JasonDavis
所以,首先,你是对的,有很多方法可以在javascript中表达事物。主要原因在于,在JS中,每当你写东西的时候,你都必须比大多数其他语言更加注意运行时环境。 – Ryan