将属性存储在函数中,静态

Storing property inside function, static?

本文关键字:静态 函数 属性 存储      更新时间:2023-09-26

各位程序员,大家好,我开始学习JavaScript了。这个语法是纯粹的巫术,有人可以澄清一下:

function CleanPet(){
    alert("The pet is now clean!");
}
CleanPet.Description="Dirty Business";

我正在阅读的材料解释说,在 JavaScript 中,函数就像任何其他对象一样,但是如果我将属性附加到函数,这是否意味着它是静态的,因为我实际上还没有声明它?

感谢您的帮助,一

对象属性不是像对变量那样使用var的正式意义上的"声明"。给定一个现有的对象CleanPet ,您可以分配像 CleanPet.Description 这样的属性(如问题中),如果它不存在,它将创建 Description 属性,或者覆盖该属性(如果它已经存在)。

尝试访问尚未设置的对象属性也是"合法的",例如,CleanPet.SomeOtherProperty - 结果值将undefined。(不是错误,尽管这假设CleanPet实际上是一个对象。如果CleanPet nullundefinedCleanPet.SomeOtherProperty会给出错误。

因此,具体到函数,函数声明:

 function CleanPet { /* some code */ }

。声明恰好是函数的单个对象。这意味着你可以将其作为函数CleanPet()调用,但它仍然具有"普通"的对象行为,例如分配属性的能力。

JavaScript 函数也是对象构造函数,如果使用 new 调用:

var cleanPet1 = new CleanPet();

在这种情况下,每次调用 new CleanPet() 时,JS 都会创建一个新对象(实例),但无法通过 cleanPet1.Description 访问 CleanPet.Description 属性,因为它是构造函数的属性,而不是生成的new实例的属性。所以从这个意义上说,是的,该属性是"静态的"。

javascript 中的函数是对象,可以具有属性。

当您将属性

分配给函数(如示例中所示)时,它会在该函数对象上创建一个新属性,并且它的行为本质上类似于与函数本身相同范围内的变量,但该属性的作用域仅为函数名称,因此不会污染全局名称空间。

这样做有几个原因:

  1. 您需要一个全局变量,该变量在函数的一次调用到另一个调用时保持其值。
  2. 您不想污染此新变量的全局命名空间。
  3. 您喜欢封装与它们相关的函数关联的全局变量的想法。
  4. 您希望优化代码,以便每次运行函数时都不会重新计算静态或常量声明。

在您的示例中,您看到了这四种方法的好处。

是的,函数/类的属性是静态

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;
}

这里有几点需要注意:

  1. 函数main在声明之前被调用。这是可能的,因为声明是悬挂的。无需前向声明。
  2. "
  3. 类"(咳咳,"构造函数")Square简单而小。
  4. 公共属性(或函数)将添加到 this 指向的对象中。
  5. 其他一切都是私有的(只能通过关闭访问)。

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