在 JavaScript 中使用“原型"与“这个"? [英] Use of 'prototype' vs. 'this' in JavaScript?

查看:35
本文介绍了在 JavaScript 中使用“原型"与“这个"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有什么区别

var A = function () {
    this.x = function () {
        //do something
    };
};

var A = function () { };
A.prototype.x = function () {
    //do something
};

推荐答案

这些例子有非常不同的结果.

The examples have very different outcomes.

在查看差异之前,应注意以下几点:

Before looking at the differences, the following should be noted:

  • 构造函数的原型提供了一种通过实例的私有[[Prototype]]属性在实例之间共享方法和值的方法.
  • 一个函数的this是通过函数的调用方式或bind的使用来设置的(这里不讨论).如果在对象上调用函数(例如 myObj.method()),则方法中的 this 引用该对象.如果 this 不是通过调用或使用 bind 设置的,它默认为全局对象(浏览器中的窗口)或在严格模式下,保持未定义.
  • JavaScript 是一种面向对象的语言,即大多数值都是对象,包括函数.(字符串、数字和布尔值不是对象.)
  • A constructor's prototype provides a way to share methods and values among instances via the instance's private [[Prototype]] property.
  • A function's this is set by how the function is called or by the use of bind (not discussed here). Where a function is called on an object (e.g. myObj.method()) then this within the method references the object. Where this is not set by the call or by the use of bind, it defaults to the global object (window in a browser) or in strict mode, remains undefined.
  • JavaScript is an object-oriented language, i.e. most values are objects, including functions. (Strings, numbers, and booleans are not objects.)

这里是有问题的片段:

var A = function () {
    this.x = function () {
        //do something
    };
};

在这种情况下,变量 A 被分配了一个值,该值是对函数的引用.当使用 A() 调用该函数时,该函数的 this 不是由调用设置的,因此它默认为全局对象和表达式 this.x 是有效的 window.x.结果是对右侧函数表达式的引用分配给了 window.x.

In this case, variable A is assigned a value that is a reference to a function. When that function is called using A(), the function's this isn't set by the call so it defaults to the global object and the expression this.x is effective window.x. The result is that a reference to the function expression on the right-hand side is assigned to window.x.

在以下情况下:

var A = function () { };
A.prototype.x = function () {
    //do something
};

发生了非常不同的事情.在第一行,变量 A 被分配了一个对函数的引用.在 JavaScript 中,所有函数对象默认都有一个 prototype 属性,因此没有单独的代码来创建 A.prototype 对象.

something very different occurs. In the first line, variable A is assigned a reference to a function. In JavaScript, all functions objects have a prototype property by default so there is no separate code to create an A.prototype object.

在第二行中,A.prototype.x 被分配了一个对函数的引用.如果它不存在,这将创建一个 x 属性,或者如果它存在则分配一个新值.因此,与第一个示例的不同之处在于,表达式中涉及对象的 x 属性.

In the second line, A.prototype.x is assigned a reference to a function. This will create an x property if it doesn't exist, or assign a new value if it does. So the difference with the first example in which object's x property is involved in the expression.

下面是另一个例子.它类似于第一个(也许你想问的是什么):

Another example is below. It's similar to the first one (and maybe what you meant to ask about):

var A = new function () {
    this.x = function () {
        //do something
    };
};

在本例中,new 运算符已添加到函数表达式之前,以便将函数作为构造函数调用.当使用 new 调用时,函数的 this 被设置为引用一个新对象,该对象的私有 [[Prototype]] 属性被设置为引用构造函数的公共原型.因此,在赋值语句中,将在这个新对象上创建 x 属性.当作为构造函数调用时,函数默认返回它的 this 对象,因此不需要单独的 return this; 语句.

In this example, the new operator has been added before the function expression so that the function is called as a constructor. When called with new, the function's this is set to reference a new Object whose private [[Prototype]] property is set to reference the constructor's public prototype. So in the assignment statement, the x property will be created on this new object. When called as a constructor, a function returns its this object by default, so there is no need for a separate return this; statement.

要检查 A 是否具有 x 属性:

To check that A has an x property:

console.log(A.x) // function () {
                 //   //do something
                 // };

这是 new 的不常见用法,因为引用构造函数的唯一方法是通过 A.constructor.这样做会更常见:

This is an uncommon use of new since the only way to reference the constructor is via A.constructor. It would be much more common to do:

var A = function () {
    this.x = function () {
        //do something
    };
};
var a = new A();

实现类似结果的另一种方法是使用立即调用的函数表达式:

Another way of achieving a similar result is to use an immediately invoked function expression:

var A = (function () {
    this.x = function () {
        //do something
    };
}());

在这种情况下,A 分配了调用右侧函数的返回值.再次,由于this没有在调用中设置,它将引用全局对象并且this.x是有效的window.x.由于该函数不返回任何内容,A 的值为 undefined.

In this case, A assigned the return value of calling the function on the right-hand side. Here again, since this is not set in the call, it will reference the global object and this.x is effective window.x. Since the function doesn't return anything, A will have a value of undefined.

如果您将 Javascript 对象序列化为 JSON 或从 JSON 反序列化,则这两种方法之间的这些差异也很明显.当您序列化对象时,在对象原型上定义的方法不会被序列化,例如,当您只想序列化对象的数据部分而不是方法时,这会很方便:

These differences between the two approaches also manifest if you're serializing and de-serializing your Javascript objects to/from JSON. Methods defined on an object's prototype are not serialized when you serialize the object, which can be convenient when for example you want to serialize just the data portions of an object, but not it's methods:

var A = function () { 
    this.objectsOwnProperties = "are serialized";
};
A.prototype.prototypeProperties = "are NOT serialized";
var instance = new A();
console.log(instance.prototypeProperties); // "are NOT serialized"
console.log(JSON.stringify(instance)); 
// {"objectsOwnProperties":"are serialized"} 

相关问题:

旁注:这两种方法可能不会显着节省内存,但是使用原型来共享方法和属性可能比每个拥有自己副本的实例使用更少的内存.

Sidenote: There may not be any significant memory savings between the two approaches, however using the prototype to share methods and properties will likely use less memory than each instance having its own copy.

JavaScript 不是低级语言.将原型设计或其他继承模式视为显式更改内存分配方式的一种方式可能不是很有价值.

JavaScript isn't a low-level language. It may not be very valuable to think of prototyping or other inheritance patterns as a way to explicitly change the way memory is allocated.

这篇关于在 JavaScript 中使用“原型"与“这个"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆