Javascript 为什么google闭包编译器会警告数组的长度?

Javascript 为什么google闭包编译器会警告数组的长度?,javascript,arrays,google-closure-compiler,Javascript,Arrays,Google Closure Compiler,我有一个对象,其属性始终是数组或空值,如下所示: /** @constructor */ function MyObject() { // optionalProperty always contains an array or null this.optionalProperty = null; } MyObject.prototype.initialize = function() { this.optionalProperty = [1,2,3]; }; va

我有一个对象,其属性始终是数组或空值,如下所示:

/** @constructor */
function MyObject() {
    // optionalProperty always contains an array or null
    this.optionalProperty = null;
}

MyObject.prototype.initialize = function() {
     this.optionalProperty = [1,2,3];
};

var foo = new MyObject();
foo.initialize();

if(Array.isArray(foo.optionalProperty)) {
    var length = foo.optionalProperty.length;
}
Google closure compiler警告说,foo.optionalProperty上永远不会定义属性长度,即使如果执行检查长度的代码行,它显然是一个数组,当然数组也有一个长度属性。消除/抑制此警告的建议

更新: 好吧,所以我有点傻。我试图从我的代码库中准备一个最小的问题示例,但正如Chad指出的,这个示例实际上并没有抛出编译器警告。所以我继续挖掘,在我的代码库中找到了另一个地方,在那里我将属性作为对象而不是数组来处理!这里有一个更好的代码片段来查看警告:

/** @constructor */
function MyObject() {
    // optionalProperty always contains an array or null
    this.optionalProperty = null;
}

MyObject.prototype.initialize = function() {
    this.optionalProperty = {};
    this.optionalProperty.a = 1;
};

MyObject.prototype.otherMethod = function() {
    if(Array.isArray(this.optionalProperty)) {
        for (var i = 0; i < this.optionalProperty.length; i++) {
            console.log(i);
        }
    }
};

var foo = new MyObject();
foo.initialize();
foo.otherMethod();
/**@构造函数*/
函数MyObject(){
//optionalProperty始终包含数组或null
this.optionalProperty=null;
}
MyObject.prototype.initialize=函数(){
this.optionalProperty={};
this.optionalProperty.a=1;
};
MyObject.prototype.otherMethod=函数(){
if(Array.isArray(this.optionalProperty)){
对于(var i=0;i
因此,“长度”属性之前未定义的警告是合法的。如果我像owler指出的那样键入this.optionalProperty,我一开始就不会有这种混乱,因为如果您试图将数组分配给某个应该是对象的对象,编译器会发出警告。我仍然认为编译器可以更智能地在块内进行类型检查,比如 if(Array.isArray(something)){}
但是这里的问题肯定是用户错误。

您需要告诉编译器属性的类型,类似这样

function MyObject() {
    /** optionalProperty always contains an array or null
    * @type {?Array}
    */
    this.optionalProperty = null;
}

MyObject.prototype.initialize = function() {
     this.optionalProperty = [1,2,3];
}

foo = new MyObject();
foo.initialize();

if (this.optionalProperty != null) {
    var length = foo.optionalProperty.length;
}
您也可以在那里使用
goog.isArray()。我不知道编译器是否会识别
Array.isArray
,它可能会。但是从定义来看,如果它不是null,那么它就是一个数组,编译器知道这一点


闭包wiki有一个很好的页面,名为

,您需要告诉编译器属性的类型,类似这样

function MyObject() {
    /** optionalProperty always contains an array or null
    * @type {?Array}
    */
    this.optionalProperty = null;
}

MyObject.prototype.initialize = function() {
     this.optionalProperty = [1,2,3];
}

foo = new MyObject();
foo.initialize();

if (this.optionalProperty != null) {
    var length = foo.optionalProperty.length;
}
您也可以在那里使用
goog.isArray()。我不知道编译器是否会识别
Array.isArray
,它可能会。但是从定义来看,如果它不是null,那么它就是一个数组,编译器知道这一点


closure wiki有一个很好的页面,名为

这是一个错失的机会-在由
数组保护的if语句中。isArray
检查,编译器可以收紧类型。请参阅我上面的更新--这个答案实际上并没有解释编译器警告的原因,因为这是由原始帖子中没有的哑代码引起的。但是,按此处所示键入变量是一种非常好的做法,并且会标记前面提到的哑代码,因此我将接受/投票此答案。这是一个错过的机会-在由
数组保护的if语句中。isArray
检查,编译器可能会收紧类型。请参阅上面我的更新——这个答案实际上并没有解释编译器警告的原因,因为这是由原始帖子中没有的哑代码引起的。但是,如图所示键入变量是一种非常好的做法,并且会标记前面提到的哑代码,因此我将接受/更新此答案。您使用的是旧版本的编译器吗?较新的版本正确地识别了
foo.optionalProperty
的类型-您上面的测试代码在没有警告的情况下为我工作(经过一些修改)。将
/**@constructor*/
添加到
函数MyObject
var
以正确定义
foo
;但我刚刚更新到9月14日的版本,仍然收到警告。我将更正上面的示例代码,很好地捕捉到缺少的jsdoc和变量声明。您使用的是旧版本的编译器吗?较新的版本正确地识别了
foo.optionalProperty
的类型-您上面的测试代码在没有警告的情况下为我工作(经过一些修改)。将
/**@constructor*/
添加到
函数MyObject
var
以正确定义
foo
;但我刚刚更新到9月14日的版本,仍然收到警告。我将更正上面的示例代码,很好地捕捉到缺少的jsdoc和变量声明。