我一直在使用javascript并且总是使用这种表示法来创建对象
var className = (function() {
var property = 1; //Example of a property
var method = function () {
//Example of a method
};
});
但现在我有一个项目,我使用AngularJs并且javascript无法识别它。我可以用这个
var className = (function() {
this.property = 1; //Example of a property
this.method = function() {
//Example of a method
};
});
有没有理由让第一个不工作?根据我的经验,我更喜欢第一个更好的
[编辑]
var className = (function() {
var property = 1; //Example of a property
var method = function () {
//Example of a method
};
})();
答案 0 :(得分:1)
var className = (function() {
var property = 1; //Example of a property
var method = function () {
//Example of a method
};
});
在此示例中,您实际上并未创建超越属性和/或方法的任何内容。您只是将函数分配给变量className
,并且在该函数中您还要创建另外两个变量。变量是功能范围的,根据定义,在函数外部不可见。
答案 1 :(得分:0)
如果您使用AngularJS,那么OOP有不同的范围和理解。您可能必须知道$scope
这是Angular对象,方法等的范围。请查看documentation,同时阅读有关Angular范围的更多信息。
在您的情况下,您应该在某些控制器或服务(工厂,指令)中使用此代码并具有以下内容:
angular.module('myapp', [])
.controller('MyCtrl', ['$scope', function($scope) {
$scope.myvar = 'hello';
$scope.mymethod = function() {
console.log($scope.myvar);
};
}])
答案 2 :(得分:0)
这两个例子做了两件非常不同的事情。
首先,在调用className()时,您实际上并没有在新创建的对象上创建任何属性。在函数中使用var声明的任何内容都只是该函数的本地范围值,这意味着一旦离开该函数,您就无法访问它。
第二个实际上会在新创建的对象上创建属性和方法。但是,在定义构造函数时,更常见的是这样做:
function ClassName() {
this.property = 'some property value'
}
构造函数通常是大写的,但这只是一种风格指南。
然后在构造函数的原型上定义成员函数,如下所示:
ClassName.prototype.method = function() {
// function body where "this" refers to an instance of ClassName
}
然后你可以像这样使用构造函数:
var someObject = new ClassName()
答案 3 :(得分:0)
要了解此行为,您需要了解JavaScript如何处理范围。
JavaScript中唯一的范围是函数范围。要了解这意味着什么,请考虑您在其他编程语言中看到的其他类型的范围,例如循环,类和if-else语句。在范围内创建变量时,无法在该范围之外访问该变量。
因为唯一的JavaScript范围是函数范围,所以这两种方法在功能上是相同的:
function myFunc(){
var x = 5; // variable declared outside loops
for(var i = 0; i < x; i++){ // iterator variable declared in loop params
var y = i; // variable declared inside a loop
for(var i = 10; i > 6; i--){
var z = i; // variable declared inside another loop
}
}
}
function myFunc(){
var x, i, y, z; // all variables declared at beginning of function
x = 5;
for(i = 0; i < x; i++){
y = i;
for(i = 10; i > 6; i--){
z = i;
}
}
}
请注意,在JavaScript中,在同一范围内的for
循环中使用相同的迭代器变量是一个逻辑错误,因为它们将引用相同的变量(那里没有&# 34;循环范围&#34;区分它们。)
另一方面,函数范围可用于防止变量名称发生冲突,因为变量不能在其范围之外访问。
请注意,在下面的示例中,我们有两个名为x
的不同的变量。它们是不同的,因为它们存在于不同的功能范围内。
var x = "Outer Scope";
(function(){
var x = "Inner Scope";
alert(x); // output: "Inner Scope"
})();
alert(x); // output: "Outer Scope"
外部作用域无法访问内部作用域中x
的值。
这使我们采用JavaScript方式创建类似对象的语法。
在第一个示例中,变量property
和method
无法在&#34;构造函数&#34;之外访问。或者&#34;类定义&#34; (或者你想要用来创建对象的函数),因为它们被包裹在函数范围内。你几乎可以将它们视为私人成员。
在第二个示例中,您使用this
关键字将变量附加为&#34;构造函数&#34;返回的对象的属性。可以通过函数范围外的代码访问对象属性 。将它们视为公共成员。
如果它有助于将事物放入面向对象的引用框架中,您甚至可以使用该语法来提供getter和setter(访问器和更改器),就像这样。
var className = function() {
var property = 1;
this.getProperty = function(){return property;};
this.setProperty = function(value){property = value;};
};
var obj = new className();
obj.getProperty(); // 1
obj.setProperty(200);
obj.getProperty(); // 200
typeof(obj.property); // "undefined"
getProperty()
和setProperty()
函数能够访问属性,因为它们是在同一函数范围内定义的;要更清楚地理解这一点,请查看&#34;关闭。&#34;
从性能角度来看,您可能不希望在&#34;类定义中定义许多功能&#34;如上所述,因为这导致对象的每个实例具有其自己的函数副本(这增加了每个对象所需的存储量)。相反,您可以将方法附加到函数的 prototype ,因此方法定义一次。
className.prototype.getDouble = function(){return this.getProperty()*2;};
obj.getDouble(); // 400
需要注意的一点是,原型函数也受函数范围的约束,因此它们无法访问您在&#34;类定义中定义的变量。&#34;
className.prototype.getTriple = function(){return property*3;};
obj.getTriple(); // ERROR: "'property' is undefined"