Class 变量的 Javascript 等价物是什么?

What is the Javascript equivalent of a Class variable?

编辑:感谢@Aadit M Shah 的确认。

function Apple () {}
Apple.someVar = null; // Class variable
Apple.prototype.someVar = null; // Instance variable

JavaScript 是一种函数式语言, class 典型编程语言的特性不受直接支持,但可以通过闭包的概念实现。

在您提供的代码片段中,Apple.someVar 和 Apple.prototype.someVar 对于从 Apple 构造函数创建的所有对象都具有相同的值,即像 class 变量。

要实现实例变量的功能,使用闭包。 您可以在线查找有关闭包的更多帮助,这里是参考 http://javascript.crockford.com/private.html

我提供了一个小代码片段来说明这一点。

function Apple(property){
  var color = property.color; //instance variable
  this.getColor = function(){
    return color;
 };  
}
Apple.type = "fruit"; //class variable

var redApple = new Apple({color:'red'});
var greenApple = new Apple({color:'green'});  

变量 redApple 和 greenApple 共享相同的 属性 'type' 但每个变量都有自己的颜色 属性.

在基于 class 的语言(即 Java)中,静态成员是使用特殊语法创建的,并且可以像 class 本身的成员一样使用。

在Java脚本中没有特殊的语法来表示静态属性。但是,您可以通过使用构造函数并向其添加属性来实现这种 classy 行为。与所有其他函数一样,构造函数是对象并且可以具有属性。

让我们看一个例子:

我们有 Car 的构造函数、Car 的静态方法和 Car 的 "instance"(原型委托)方法。

// constructor
var Car = function () {};

// a static method
Car.isShiny = function () {
  return "bling bling";
};

// "instance" method added to the prototype
Car.prototype.setPrice = function (price) {
  this.price = price;
};

正如预期的那样,我们可以调用静态方法和 "instance" 方法。

// calling a static method
Car.isShiny(); // "bling bling"

// creating an instance and calling a method
var ford = new Car();
ford.setPrice(5000);

静态调用 "instance" 方法将不起作用。 同样,在实例上调用静态方法也是行不通的。

typeof Car.setPrice; // "undefined"
typeof ford.isShiny; // "undefined"

在实例上调用静态方法有一个解决方法。定义一个原型方法,引用静态方法。

Car.prototype.isShiny = Car.isShiny;
ford.isShiny(); // "bling bling"

但是,这会带来一些我们需要注意的复杂情况。如果在静态方法中使用关键字 this,将引用 Car 构造函数或 ford 实例,具体取决于调用者。

静态和非静态调用相同的方法是可能的。在instanceof的帮助下,我们可以知道该方法是如何被调用的。

// constructor
var Car = function (price) {
  this.price = price;
};

// a static method
Car.isShiny = function () {

  // this always works
  var msg = "bling bling";

  if (this instanceof Gadget) {
    // this only works if called non-statically
    msg += ", it costs $" + this.price + '!';
  }

  return msg;
};

// a normal method added to the prototype
  Car.prototype.isShiny = function () {
  return Car.isShiny.call(this);
};

// static call
Car.isShiny(); // "bling bling"

//non static call
var benz = new Car('9999.99');
benz.isShiny(); // "bling bling, it costs 99.99!"

该示例说明了 public 静态成员的使用。在 Java脚本中,您也可以实现私有静态成员。

参考:Java脚本模式书。

tl;博士

function Apple () {}
Apple.someVar = null; // property on the constructor - doesn't affect instances
Apple.prototype.someVar = null; // the default value of the `someVar` property on instances returned by the constructor when using the `new` keyword

这是一个更详细的例子,可以看到它的实际效果:

function Apple () {}

Apple.color = 'blue'; // this doesn't do what you think it does.

console.log('Apple.color:', Apple.color); // blue

console.log('---'); 

// basic instantiation of the apples
var goldenDelicious = new Apple();
var grannySmith = new Apple();
var fuji = new Apple();

console.log('goldenDelicious.color:', goldenDelicious.color); // undefined
console.log('grannySmith.color:', grannySmith.color); // undefined
console.log('fuji.color:', fuji.color); // undefined

console.log('---'); 

fuji.color = 'red';

Apple.prototype.color = 'green'; 
// overrides color properties of all apples that have not 
// had their color set - even those of instances already created
// This is because their value is the default, and we are 
// modifying that default.

console.log('goldenDelicious.color:', goldenDelicious.color); // green
console.log('grannySmith.color:', grannySmith.color); // green
console.log('fuji.color:', fuji.color); // red

console.log('---'); 

// assign some actual colors

goldenDelicious.color = 'yellow';
grannySmith.color = 'green';
fuji.color = 'red';

console.log('goldenDelicious.color:', goldenDelicious.color); // yellow
console.log('grannySmith.color:', grannySmith.color); // green
console.log('fuji.color:', fuji.color); // red

console.log('---'); 

Apple.prototype.color = 'orange'; // all new apples will default to orange

var honeyCrisp = new Apple();

console.log('goldenDelicious.color:', goldenDelicious.color); // yellow
console.log('grannySmith.color:', grannySmith.color); // green
console.log('fuji.color:', fuji.color); // red
console.log('honeyCrisp.color:', honeyCrisp.color); // orange