简体   繁体   English

JavaScript中的var thing和function thing()有什么区别?

[英]What is the difference between var thing and function thing() in JavaScript?

I was just wondering about the difference between the following declaration of JavaScript objects. 我只是想知道以下JavaScript对象声明之间的区别。 Specifically, the difference between thing object literal and thing1 object from thing class. 具体来说,事物类中的事物对象文字和事物1对象之间的区别。

Code: 码:

var thing = {
    sanity:0,
    init:function(){
        //code
    },
    send:function(){
        //code
    }
}

function thing(){
    this.sanity = 0;
    this.init = function(){
        //code
    };
    this.send = function(){
        //code
    };
}

thing1 = new thing();

Static Objects / Object Literals 静态对象/对象文字

Static objects, or object literals, don't require instantiation with the new operator and also behave like singletons. 静态对象或对象文字不需要使用new运算符进行实例化,也可以像单例一样运行。 Consider the following example: 请考虑以下示例:

Code: 码:

var staticObject1 = {
 a: 123,
 b: 456
};
var staticObject2 = staticObject1;
console.log(staticObject1, staticObject2);
staticObject2.b = "hats";
console.log(staticObject1, staticObject2);

Output: 输出:

Object a=123 b=456  Object a=123 b=456
Object a=123 b=hats Object a=123 b=hats

Notice that changing staticObject2.b also affected staticObject1.b . 请注意,更改staticObject2.b也会影响staticObject1.b However, this may not always be the desired effect. 然而,这可能并不总是期望的效果。 Many libraries, such as Dojo , offer an object cloning method that can alleviate this situation if you want to make a copy of a static object. 许多库(如Dojo )提供了一种对象克隆方法,如果要复制静态对象,可以缓解这种情况。 Continuing the previous example, consider the following: 继续前面的示例,请考虑以下事项:

Code: 码:

var staticObject3 = dojo.clone(staticObject1); // See the doc in the link above
staticObject1.a = "pants";
console.log(staticObject1, staticObject2, staticObject3);

Output: 输出:

Object a=pants b=hats Object a=pants b=hats Object a=123 b=hats

Notice that the values of the members of staticObject1 and staticObject2 are the same, whereas staticObject3 is not affected by changes to these other objects. 请注意, staticObject1staticObject2的成员的值是相同的,而staticObject3不受对这些其他对象的更改的影响。

Static objects are also useful for creating project or library namespaces, rather than filling up the global scope, and promotes compatibility like no one's business. 静态对象对于创建项目或库命名空间也很有用,而不是填满全局范围,并提升兼容性,就像没有人的业务一样。

This is useful when creating libraries that require portability or interoperability. 在创建需要可移植性或互操作性的库时,这非常有用。 This can be seen in popular libraries such as Dojo, YUI and ExtJs, where all or most methods are called as dojo.examplMethod() , YUI().exampleMethod() , or Ext.exampleMethod() respectively. 这可以在流行的库中看到,例如Dojo,YUI和ExtJs,其中所有或大多数方法分别被称为dojo.examplMethod()YUI().exampleMethod() Ext.exampleMethod()Ext.exampleMethod()

Static objects can also be considered loosely analogous to struct 's in C/C++. 静态对象也可以被认为与C / C ++中的struct类似。

Class Constructors / Instantiated Objects 类构造函数/实例化对象

Classes in JavaScript are based on prototypal inheritance, which is a far more complex subject and can be read about here , here and here . JavaScript中的类基于原型继承,这是一个更复杂的主题,可以在这里这里这里阅读

As opposed to static objects, this method of object creation gives the unique opportunity for private scope object members and methods because of JavaScript's closuer property. 与静态对象相反,由于JavaScript的closuer属性,这种对象创建方法为私有范围对象成员和方法提供了独特的机会。 Consider the following example of private class members: 请考虑以下私有类成员示例:

Code: 码:

var SomeObject = function() {
    var privateMember = "I am a private member";
    this.publicMember = "I am a public member";

    this.publicMethod = function() {
        console.log(privateMember, this.publicMember);
    };
};

var o = new SomeObject();
console.log(typeof o.privateMember, typeof o.publicMember);
o.publicMethod();

Output: 输出:

undefined string
I am a private member I am a public member

Notice that typeof o.privateMember is "undefined" and not accessible outside of the object, but is from within. 请注意, typeof o.privateMember是“未定义的”,不能在对象外部访问,但是来自内部。

Private methods can also be made, but are not as straight forward yet are still simple to implement. 也可以制作私有方法,但不是那么简单,但仍然很容易实现。 The issue lies in that the value of this inside of the private method defaults to window and one of two techniques must be applied to ensure that this refers to the object that we are working within, in this case, the instance of SomeObject . 问题在于,值this私有方法默认的内部window和两种技术之一必须应用,以确保this指的是我们中工作,在这种情况下,对象实例SomeObject Consider the following example: 请考虑以下示例:

Code: 码:

var SomeObject = function() {
    var privateMember = "I am a private member";
    var privateMethod = function() {
        console.log(this.publicMember);
    };

    this.publicMember = "I am a public member";
    this.publicMethod = function() {
        console.log(privateMember, this.publicMember);
    };
    this.privateMethodWrapper = function() {
        privateMethod.call(this);
    }
};

var o = new SomeObject();
console.log(typeof o.privateMethod, typeof o.publicMethod, typeof o.privateMethodWrapper);
o.privateMethodWrapper();

Output: 输出:

undefined function function
I am a public member

Notice that withing privateMethodWrapper() , privatemethod was executed using call and passing in this for the function's context. 请注意,withing privateMethodWrapper() privatemethod使用执行call和传递this对函数的上下文。 This is all fine; 这一切都很好; however, the following technique is preferable (in my opinion) as it simplifies the calling scope and produces identical results. 但是,以下技术是优选的(在我看来),因为它简化了调用范围并产生相同的结果。 The previous example can be changed to the following: 上一个示例可以更改为以下内容:

Code: 码:

var SomeObject = function() {
    var self          = this;
    var privateMember = "I am a private member";
    var privateMethod = function() {
        console.log(self.publicMember);
    };

    this.publicMember = "I am a public member";
    this.publicMethod = function() {
        console.log(privateMember, this.publicMember);
    };
    this.privateMethodWrapper = function() {
        privateMethod();
    }
};

var o = new SomeObject();
console.log(typeof o.privateMethod, typeof o.publicMethod, typeof o.privateMethodWrapper);
o.privateMethodWrapper();

Output: 输出:

undefined function function
I am a public member

This answer was the basis for a post on my blog , where I give additional examples. 这个答案是我博客上帖子的基础,我在这里给出了更多的例子。 Hope that helps ;) 希望有所帮助;)

Case 2 is referencing javascript class constructors . 案例2引用了javascript 类构造函数 A glaring difference is that the variable is not yet an object, so you cannot internally reference thing1.sanity. 一个明显的区别是变量还不是一个对象,所以你不能在内部引用thing1.sanity。 You would have to initialize the class by creating an instance of said class prior to calling any internal members: 您必须在调用任何内部成员之前通过创建所述类的实例来初始化该类:

var myConstructor = function() {
    this.sanity = 0;
}

// wont work
alert(myConstructor.sanity);

// works
var thing1 = new myConstructor();
alert(thing1.sanity);

Here is an article going further in-depth than my quick example: 这篇文章比我的快速示例更深入:

Class Constructors vs. Object Literals 类构造函数与对象文字

The difference is that the thing1 object is associated with the thing1 class, and will inherit (not literally) the thing1 prototype. 不同之处在于thing1对象与thing1类相关联,并且将继承(不是字面上) thing1原型。

For example, you can later write 例如,您可以稍后写

thing.prototype.initAndSend = function() { this.init(); this.send(); };

You will then be able to write thing1.initAndSend() without modifying thing1 . 然后,您将能够编写thing1.initAndSend()而无需修改thing1 In addition, thing1.constructor will be equal to the thing method, whereas {}.constructor is equal to Object . 另外, thing1.constructor将等于thing方法,而{}.constructor等于Object

By the way, standard convention is to capitalize class names. 顺便说一句,标准惯例是大写类名。

With the first method, you are declaring a single object. 使用第一种方法,您将声明一个对象。 With the second, you are declaring a class from which you can instantiate (ie create) many different copies. 对于第二个,您将声明一个类,您可以从中实例化(即创建)许多不同的副本。

Functions are objects and also constructors (you can instantiate them using new ). 函数是对象和构造函数(您可以使用new实例化它们)。

Hash-tables/Objects ( {} ) are not able to be instantiated, thus they are commonly used as data structures. 散列表/对象( {} )无法实例化,因此它们通常用作数据结构。 And I am not so sure if it is wise to call them "Objects". 我不太确定将它们称为“物体”是否明智。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM