嗯...看来您不知道 JavaScript 内部是如何工作的,所以这里是一个快速回顾。 :)
使用 ES5 语法,有两种方法来创建所谓的“类”:
当您使用对象文字时,您的类如下所示:
var myClass = {
myAttribute: "foo",
myMethod: function () {
return "bar";
}
};
当您使用构造函数时,您的类如下所示:
function MyClass() {
this.myAttribute = "foo";
this.myMethod = function () {
return "bar";
};
}
这两种方法当然存在差异。有了对象字面量,你就有了一种单例,其中属性在某种程度上都是静态的。使用构造函数,您可以生成实例,其属性将由this关键词。例子:
var myInstance = new MyClass();
console.log(myInstance);
该实例将包含“myAttribute”和“myMethod”自己的财产。这意味着这些属性与实例相关联。如果你想调用这个方法,你必须这样做:
myInstance.myMethod();
到目前为止一切顺利...但是我们之前所做的有一些问题。this.myMethod
将为每个实例一次又一次地创建MyClass
而且总是一样的。处理这个问题的更好方法是将其放入原型以便所有实例可以共享它:
function MyClass() {
this.myAttribute = "foo";
}
MyClass.prototype.myMethod = function () {
return "bar";
};
这好多了,但是myMethod
仍然与MyClass
实例...
现在我想创建一个静态方法。根据定义,我们的静态方法将绑定到类,而不是它的实例:
MyClass.myStaticMethod = function () {
return "baz";
};
好的。在这里,为了实验的目的,我想做这样的事情:
MyClass.myStaticMethod = function () {
myMethod();
};
这是行不通的。为什么?实际上,myMethod
既不存在于给定范围内,也不存在于外部范围内。myMethod
已在另一个函数(构造函数)内声明并且不返回,因此从外部是不可见的。而且这个函数已经被放到了原型中MyClass
。这意味着它在全局范围内不可用,而仅在实例上可用MyClass
。当你仔细想想,这是非常合乎逻辑的。例如,当你想调用数组方法(Array.prototype 中的方法)时,这样做是没有意义的:
push('test');
reverse();
includes('a');
您必须在数组(数组实例)上调用这些方法。
[].push('test');
['foo', 'bar', 'baz'].reverse();
['a', 'b'].includes('a');