在函数内部存储属性,静态?

时间:2013-01-27 04:50:01

标签: javascript

Hello其他程序员,我已经学习了JavaScript。这种语法是纯粹的巫术,有人可以澄清:

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

CleanPet.Description="Dirty Business";

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

感谢您的帮助, I.N。

4 个答案:

答案 0 :(得分:3)

在使用var的形式意义上,对象属性不是“声明”的,就像你对变量一样。给定现有对象CleanPet,您可以指定CleanPet.Description之类的属性(如问题中所示),如果该属性尚不存在,则会创建Description属性,或者覆盖该属性确实存在。

尝试访问尚未设置的对象属性也是“合法的”,例如CleanPet.SomeOtherProperty - 结果值为undefined。 (不是错误,但假设CleanPet实际上是一个对象。如果CleanPetnullundefined,则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中的函数是对象,可以具有属性。

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

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

  1. 您需要一个全局变量,该函数从函数的一次调用到另一次调用时保持其值。
  2. 您不希望污染此新变量的全局命名空间。
  3. 您喜欢封装与其相关的函数关联的全局变量的想法。
  4. 您希望优化代码,以便每次运行函数时都不会重新评估静态或常量声明。
  5. 在你的例子中,你看到了所有四个人的好处。

答案 3 :(得分: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在声明之前被调用。这是可能的,因为声明是hoisted。无需转发声明。
  2. Square“类”(嗯,“构造函数”)简单而小巧。
  3. 公共属性(或函数)将添加到this指向的对象。
  4. 其他所有内容都是私密的(只能通过closures访问)。
  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 ++允许您在类上声明静态属性和方法。这就像使用类作为对象一样。您也可以使用函数作为对象。这些被称为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 ++中相同代码之间的大小差异?你决定哪种语法是纯粹的巫术。 =)

    4。结论

    如果您在JavaScript中使用OOP,那么可以使用许多经典的面向对象的库来帮助您,例如:https://github.com/javascript/augment