0

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

function CleanPet(){
    alert("The pet is now clean!");
}

CleanPet.Description="Dirty Business";

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

谢谢你的帮助,在

4

4 回答 4

3

对象属性并没有var像你对变量所做的那样在正式意义上“声明”。给定一个现有的 object CleanPet,您可以分配诸如CleanPet.Description(如问题中所示)之类的属性,如果该属性尚不存在则将创建该Description属性,或者如果该属性已存在则覆盖该属性。

尝试访问您尚未设置的对象属性也是“合法的”,例如CleanPet.SomeOtherProperty- 结果值为undefined. (不是错误,尽管假设CleanPet实际上是一个对象。如果CleanPetnullundefined然后CleanPet.SomeOtherProperty会给出错误。)

因此,特别是关于函数,函数声明:

 function CleanPet { /* some code */ }

...声明一个恰好是函数的对象。这意味着您可以将其称为 function CleanPet(),但它仍然可以获得“普通”对象行为,例如分配属性的能力。

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

var cleanPet1 = new CleanPet();

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

于 2013-01-27T04:58:49.620 回答
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)
于 2013-01-27T04:58:38.777 回答
1

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

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

有几个原因可能会这样做:

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

在您的示例中,您看到了所有四个的好处。

于 2013-01-27T05:02:02.927 回答
1

比较 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. Square类”(咳咳,“构造函数”)既简单又小。
  3. 公共属性(或函数)被添加到 指向的对象this
  4. 其他一切都是私有的(只能通过闭包访问)。

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

于 2013-01-27T05:55:23.890 回答