Controller中的Angular函数构造函数

时间:2014-08-19 02:58:48

标签: javascript angularjs

在普通的JS中,我可以这样做:

function Droppable() {
    this.relevant = true;
    this.uuid = generateUUID();
};

var generateUUID = function() {
   return '12345';
}


console.log(new Droppable); // returns Droppable {relevant: true, uuid: "12345"}

但是在Angular我有这个:

angular.module('myApp').controller('MyCtrl', ['$scope', function($scope) {

    function Droppable() {
        this.relevant = true;
        this.uuid = generateUUID();
    }

    var generateUUID = function() {
        return '12345';
    }

    // initalize droppable areas
    $scope.region1 = [new Droppable];
    $scope.region2 = [new Droppable];
    $scope.region3 = [new Droppable];

}]);

我正在尝试使用UUID创建3个可放置的区域。

但是当我这样做时,我得到' undefined不是函数' 引用this.uuid = generateUUID();

中的行function Droppable() {...}

为什么?

3 个答案:

答案 0 :(得分:1)

function Droppable() {
  this.relevant = true;
  this.uuid = generateUUID();
}
var generateUUID = function() {
  return '12345';
}

好的,这不是关于AngularJS的问题,但它更多的是关于Javascript。 阅读Javascript变量提升。 使用var关键字声明函数时,会发生两件事:创建变量,然后为其分配变量。由于javascript提升,变量声明(var generateUUID)将被提升到顶部,声明发生在你编写它的地方。

var generateUUID;   //undefined
function Droppable() {
  this.relevant = true;
  this.uuid = generateUUID(); //you are invoking undefined here.
}
generateUUID = function() {
  return '12345';
}

正确的做法是:

function Droppable() {
  this.relevant = true;
  this.uuid = generateUUID();
}
function GenerateUUID() {
  return '12345';
}

在这里,因为你使用"函数GenerateUUID()",整个事物被提升到顶部而不仅仅是变量

答案 1 :(得分:1)

将我的评论回答。您的问题是由于在分配函数表达式之前保留函数表达式,在这种情况下,变量generateUUID尚未定义。

var generateUUID = function() {
    return '12345';
}

修复它的一种方法是将其转换为函数声明,以便将其自动提升到范围的顶部。

function generateUUID () {
        return '12345';
 }

或在变量generateUUID可能的用法之前将其定义为函数引用。

//Some variable declarations, start of the scope
var generateUUID = function() {
    return '12345';
}

function Droppable() {
    this.relevant = true;
    this.uuid = generateUUID();
}

当你这样做时: -

.... Some Code ....


var generateUUID = function() {
        return '12345';
    }

.... Some Code ...

它与: -

相同
var generateUUID;
.... Some Code ....
//Any usage of this till here will cause the error that you are facing, since there is no value assigned to generateUUID yet
generateUUID = function() {
            return '12345';
  }

.... Some Code ...

有些参考: - MDNSO

Plnkr

注意: - 这个问题不应该在你的例子中发生,因为你在赋值构造函数(generateUUID)之后调用了值,可能是一个不同的用例(问题中不存在) )可能有这个问题。

答案 2 :(得分:1)

给出一些简单的例子

function Droppable() {
    this.relevant = true;
    this.uuid = generateUUID();
}

// this will throw an error because you are calling generateUUID before it initialize
console.log(new Droppable);

var generateUUID = function() {
   return '12345';
}

// this will give you actuall output what you wanted
console.log(new Droppable);

因此,当您在调用Droppable之前调用函数generateUUID时,它将起作用。像这样 -

// initializes
var generateUUID = function() {
    return '12345';
}

// initializes
function Droppable() {
    this.relevant = true;
    this.uuid = generateUUID();
}

// this will work as expected
console.log(new Droppable);

在JavaScript中,您可以用两种方法定义函数

var varibaleName = function(){

}

function variableName(){

}

存在显着差异。当您使用变量声明函数时,则在调用该变量需要注册的函数之前。

如果你这样打电话 -

varibaleName();
var varibaleName = function(){

}

这会给你一个错误。

但是,如果你这样打电话会起作用 -

varibaleName();
function varibaleName (){

}

所以这也应该有效 -

function Droppable() {
    this.relevant = true;
    this.uuid = generateUUID();
}

// this will work as expected
console.log(new Droppable);


function generateUUID() {
    return '12345';
}

希望这是有道理的。

然而在角度中这将起作用 -

var myApp = angular.module("myApp", []);

myApp.controller("MyCtrl", function($scope){

    function Droppable() {
        this.relevant = true;
        this.uuid = generateUUID();
    }

    var generateUUID = function() {
        return '12345';
    }

    // initalize droppable areas
    $scope.region1 = [new Droppable];
    $scope.region2 = [new Droppable];
    $scope.region3 = [new Droppable];

    console.log( $scope.region1 );
});

但最佳做法是 -

myApp.controller("MyCtrl", function($scope){

    // you can call this before Droppable or after
    $scope.generateUUID = function() {
        return '12345';
    }

    $scope.Droppable = function () {
        this.relevant = true;
        this.uuid = $scope.generateUUID();
    }

    // initalize droppable areas
    $scope.region1 = [new $scope.Droppable];

    console.log( $scope.region1 );
});

为什么我要调用带有$scope.前缀的那些,因为稍后您可能需要在控制器与控制器之间进行通信,即使是在指令中!

快乐的编码和快乐的原型设计!这有助于您了解事情的运作方式。