Javascript类属性和方法的工作方式不同

时间:2015-07-22 17:03:16

标签: javascript oop

我一直在使用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  
  };
})();

4 个答案:

答案 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方式创建类似对象的语法。

在第一个示例中,变量propertymethod无法在&#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"