各位程序员,大家好,我已经开始学习 JavaScript。这种语法是纯粹的巫术,有人可以澄清一下:
function CleanPet(){
alert("The pet is now clean!");
}
CleanPet.Description="Dirty Business";
我正在阅读的材料解释说,在 JavaScript 中,函数就像任何其他对象一样,但是如果我将属性附加到函数,这是否意味着它是静态的,因为我实际上并没有声明它?
谢谢你的帮助,在
各位程序员,大家好,我已经开始学习 JavaScript。这种语法是纯粹的巫术,有人可以澄清一下:
function CleanPet(){
alert("The pet is now clean!");
}
CleanPet.Description="Dirty Business";
我正在阅读的材料解释说,在 JavaScript 中,函数就像任何其他对象一样,但是如果我将属性附加到函数,这是否意味着它是静态的,因为我实际上并没有声明它?
谢谢你的帮助,在
对象属性并没有var
像你对变量所做的那样在正式意义上“声明”。给定一个现有的 object CleanPet
,您可以分配诸如CleanPet.Description
(如问题中所示)之类的属性,如果该属性尚不存在则将创建该Description
属性,或者如果该属性已存在则覆盖该属性。
尝试访问您尚未设置的对象属性也是“合法的”,例如CleanPet.SomeOtherProperty
- 结果值为undefined
. (不是错误,尽管假设CleanPet
实际上是一个对象。如果CleanPet
是null
或undefined
然后CleanPet.SomeOtherProperty
会给出错误。)
因此,特别是关于函数,函数声明:
function CleanPet { /* some code */ }
...声明一个恰好是函数的对象。这意味着您可以将其称为 function CleanPet()
,但它仍然可以获得“普通”对象行为,例如分配属性的能力。
如果用 调用 JavaScript 函数也是对象构造函数new
:
var cleanPet1 = new CleanPet();
在这种情况下,JS 每次调用时都会创建一个新对象(实例)new CleanPet()
,但该CleanPet.Description
属性不可访问,cleanPet1.Description
因为它是构造函数的属性,而不是结果new
实例的属性。所以从这个意义上说,是的,该属性是“静态的”。
是的,函数/类的属性是静态的
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)
javascript中的函数是对象,可以有属性。
当您将属性分配给示例中的函数时,它会在该函数对象上创建一个新属性,并且它的行为本质上类似于与函数本身在同一范围内的变量,但该属性的范围仅限于函数名称,因此它不会污染全局命名空间。
有几个原因可能会这样做:
在您的示例中,您看到了所有四个的好处。
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
在声明之前被调用。这是可能的,因为声明被提升了。无需前向声明。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++ 允许您在类上声明静态属性和方法。这就像将类用作对象一样。您也可以将函数用作对象。这些被称为函子:
#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