将属性存储在函数中,静态
Storing property inside function, static?
各位程序员,大家好,我开始学习JavaScript了。这个语法是纯粹的巫术,有人可以澄清一下:
function CleanPet(){
alert("The pet is now clean!");
}
CleanPet.Description="Dirty Business";
我正在阅读的材料解释说,在 JavaScript 中,函数就像任何其他对象一样,但是如果我将属性附加到函数,这是否意味着它是静态的,因为我实际上还没有声明它?
感谢您的帮助,一
对象属性不是像对变量那样使用var
的正式意义上的"声明"。给定一个现有的对象CleanPet
,您可以分配像 CleanPet.Description
这样的属性(如问题中),如果它不存在,它将创建 Description
属性,或者覆盖该属性(如果它已经存在)。
尝试访问尚未设置的对象属性也是"合法的",例如,CleanPet.SomeOtherProperty
- 结果值将undefined
。(不是错误,尽管这假设CleanPet
实际上是一个对象。如果CleanPet
null
或undefined
则CleanPet.SomeOtherProperty
会给出错误。
因此,具体到函数,函数声明:
function CleanPet { /* some code */ }
。声明恰好是函数的单个对象。这意味着你可以将其作为函数CleanPet()
调用,但它仍然具有"普通"的对象行为,例如分配属性的能力。
JavaScript 函数也是对象构造函数,如果使用 new
调用:
var cleanPet1 = new CleanPet();
在这种情况下,每次调用 new CleanPet()
时,JS 都会创建一个新对象(实例),但无法通过 cleanPet1.Description
访问 CleanPet.Description
属性,因为它是构造函数的属性,而不是生成的new
实例的属性。所以从这个意义上说,是的,该属性是"静态的"。
javascript 中的函数是对象,可以具有属性。
当您将属性分配给函数(如示例中所示)时,它会在该函数对象上创建一个新属性,并且它的行为本质上类似于与函数本身相同范围内的变量,但该属性的作用域仅为函数名称,因此不会污染全局名称空间。
这样做有几个原因:
- 您需要一个全局变量,该变量在函数的一次调用到另一个调用时保持其值。
- 您不想污染此新变量的全局命名空间。
- 您喜欢封装与它们相关的函数关联的全局变量的想法。
- 您希望优化代码,以便每次运行函数时都不会重新计算静态或常量声明。
在您的示例中,您看到了这四种方法的好处。
是的,函数/类的属性是静态
的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 和 C++
JavaScript 是一种像 Self 一样的面向对象的原型语言。然而,JavaScript的语法是从C/C++借来的。这就是大多数来自经典面向对象背景的程序员感到困惑的原因。
1. 公共和私人财产
请考虑以下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
指向的对象中。 - 其他一切都是私有的(只能通过关闭访问)。
2. 共享公共属性
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 版本实际上更小,因为我们不需要在类中声明属性和方法。
3. 公共静态属性
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++ 中相同代码之间的大小差异了吗?你决定哪种语法是纯粹的巫术。=)
4. 结论
如果你在JavaScript中遇到OOP问题,有很多经典的面向对象库可以帮助你,比如这个:https://github.com/javascript/augment
- Javascript,从静态函数中打印全局对象
- 指定一个具有静态值的onclick函数
- 调用Javascript中的Python函数,读取静态文件(Flask)
- 从构造函数es6调用静态方法
- 只使用常量的静态javascript函数会被编译为常量吗
- 使用静态函数返回新Promise
- JavaScript es6 从另一个类调用静态函数
- Node.js Mongoose静态函数未被调用
- Javascript - 使用闭包递增静态函数变量模拟
- 异步 JavaScript 静态函数变量
- 如何在不影响原始函数的情况下扩展javascript中的静态函数(使用新名称)
- 在coffeescript类中是否可以有一个同名的静态函数和成员函数
- javascript中的全局静态函数
- 静态函数Javascript
- 返回静态函数的哈希值为空对象
- 声明一个公共的“静态”;函数在JavaScript类中
- 在TypeScript中以类型安全的方式用静态函数从外部库扩展一个类
- 在Javascript中创建私有静态函数
- 从静态函数调用非静态函数
- 使用 ES6 静态函数时,我得到“没有这样的方法”