Hello其他程序员,我已经学习了JavaScript。这种语法是纯粹的巫术,有人可以澄清:
function CleanPet(){
alert("The pet is now clean!");
}
CleanPet.Description="Dirty Business";
我正在阅读的材料解释说,在JavaScript中,函数就像任何其他对象一样,但是如果我将一个属性附加到一个函数,这是否意味着它是静态的,因为我还没有实际声明它?
感谢您的帮助, I.N。
答案 0 :(得分:3)
在使用var
的形式意义上,对象属性不是“声明”的,就像你对变量一样。给定现有对象CleanPet
,您可以指定CleanPet.Description
之类的属性(如问题中所示),如果该属性尚不存在,则会创建Description
属性,或者覆盖该属性确实存在。
尝试访问尚未设置的对象属性也是“合法的”,例如CleanPet.SomeOtherProperty
- 结果值为undefined
。 (不是错误,但假设CleanPet
实际上是一个对象。如果CleanPet
是null
或undefined
,则CleanPet.SomeOtherProperty
会出错。)
关于函数,特别是函数声明:
function CleanPet { /* some code */ }
...声明恰好是一个函数的单个对象。这意味着您可以将其称为函数CleanPet()
,但它仍然会获得“普通”对象行为,例如分配属性的能力。
如果使用new
调用JavaScript函数也是对象构造函数:
var cleanPet1 = new CleanPet();
在这种情况下,JS每次调用new CleanPet()
时都会创建一个新对象(实例),但CleanPet.Description
属性不可通过cleanPet1.Description
访问,因为它是构造函数的属性,而不是生成的new
实例的属性。所以在这个意义上,是的,该属性是“静态的”。
答案 1 :(得分:1)
是的,函数/类的属性是静态的
MyClass.Description = "Dirty Business";
MyClass.staticFn = function() {
};
MyClass = function() {
this.var = "test";
};
MyClass.prototype.instanceFn = function() {
};
// To call an instance function
obj = new MyClass();
obj.instanceFn();
// To call a static function
MyClass.staticFunction();
// Or to access a static property
alert(MyClass.Description)
答案 2 :(得分:1)
javascript中的函数是对象,可以具有属性。
当您将属性分配给函数中的函数时,它会在该函数对象上创建一个新属性,它的行为基本上类似于与函数本身相同范围的变量,但该属性的作用域仅限于函数名称,因此它不会污染全局名称空间。
有几个原因可能会这样做:
在你的例子中,你看到了所有四个人的好处。
答案 3 :(得分:1)
JavaScript是一种像Self这样的原型面向对象语言。然而,JavaScript的语法来自C / C ++。这使得大多数来自经典面向对象背景的程序员感到困惑。
考虑以下C ++程序:
#include <iostream>
using namespace std;
class Rectangle {
int height;
int width;
public:
Rectangle(int height, int width) {
this.height = height;
this.width = width;
}
int area() {
return height * width;
}
}
int main() {
Rectangle rectangle(3, 7);
cout << rectangle.area() << endl;
return 0;
}
这会将一对一翻译成JavaScript,如下所示:
main();
function Rectangle(height, width) {
this.area = function () {
return height * width;
};
}
function main() {
var rectangle = new Rectangle(3, 7);
console.log(rectangle.area());
return 0;
}
这里有几点需要注意:
main
在声明之前被调用。这是可能的,因为声明是hoisted。无需转发声明。Square
“类”(嗯,“构造函数”)简单而小巧。this
指向的对象。在C ++中,只有内联函数在类体内定义。必须在外部定义其他所有功能。但一般来说,所有函数(包括内联函数)都在外部定义:
#include <iostream>
using namespace std;
class Rectangle {
public:
int height;
int width;
Rectangle(int height, int width);
int area();
}
Rectangle::Rectangle(int height, int width) {
this.height = height;
this.width = width;
}
int Rectangle::area() {
return this.height * this.width;
}
int main() {
Rectangle rectangle(3, 7);
cout << rectangle.area() << endl;
return 0;
}
在JavaScript中,您可以向构造函数的prototype
添加共享方法(从不创建共享属性)。这与上面的C ++程序类似。这样做的好处是JavaScript不会为构造函数的每个实例创建新方法:
main();
function Rectangle(height, width) {
this.height = height;
this.width = width;
}
Rectangle.prototype.area = function () {
return this.height * this.width;
};
function main() {
var rectangle = new Rectangle(3, 7);
console.log(rectangle.area());
return 0;
}
JavaSctipt版本实际上更小,因为我们不需要在类中声明属性和方法。
C ++允许您在类上声明静态属性和方法。这就像使用类作为对象一样。您也可以使用函数作为对象。这些被称为functors:
#include <iostream>
using namespace std;
class Rectangle {
public:
int height;
int width;
static Rectangle fromSquare(int side);
Rectangle(int height, int width);
int area();
}
static Rectangle Rectangle::fromSquare(int side) {
return new Rectangle(side, side);
}
Rectangle::Rectangle(int height, int width) {
this.height = height;
this.width = width;
}
int Rectangle::area() {
return this.height * this.width;
}
int main() {
Rectangle square = Rectangle.fromSquare(5);
cout << square.area() << endl;
return 0;
}
由于函数是JavaScript中的对象,因此您只需向其添加属性(如仿函数)。如果这些函数用作构造函数,则函数的属性称为静态属性:
main();
Rectangle.fromSquare = function (side) {
return new Rectangle(side, side);
};
function Rectangle(height, width) {
this.height = height;
this.width = width;
}
Rectangle.prototype.area = function () {
return this.height * this.width;
};
function main() {
var square = Rectangle.fromSquare(5);
console.log(square.area());
return 0;
}
就是这样。查看JavaScript和C ++中相同代码之间的大小差异?你决定哪种语法是纯粹的巫术。 =)
如果您在JavaScript中使用OOP,那么可以使用许多经典的面向对象的库来帮助您,例如:https://github.com/javascript/augment