JavaScript函数和新运算符

时间:2017-06-24 06:00:19

标签: javascript prototype

向函数对象添加属性与向对象原型添加属性之间的区别是什么。请参阅下面的代码。

var foo = function() { this.name = alert("test") };

foo.newProp = function() { ... };
var value = new foo();

// vs

foo.prototype.newProp = function() { ... }
var value = new foo();

我的困惑是当为每个代码运行此代码时会发生什么值,以及“这个”如何受到影响。

3 个答案:

答案 0 :(得分:1)

首先,我们知道函数只是对象,因为我们可以将属性附加到它。这就是案例1中发生的事情。 我们只是将属性附加到function Foo

案例1

var Foo = function(){
    this.name = "myname";
}

Foo.newProp = function(){}; 

可以简单地访问附加到函数的属性,作为访问对象属性的方式。

案例2

在这种情况下,相同的属性位于该函数的prototype。使用此function Foo创建任何对象时,默认情况下它将访问此函数。

使用该对象调用函数时,上下文this将知道调用该函数的对象,this指向调用它的对象。

Foo.prototype.newProp = function(){ console.log("function on prototype");}

var value = new Foo();

console.log(value);

同样在情况2中,由于我们正在向函数的原型添加属性,因此它们不是坐在使用该函数创建的对象上,而是放在该对象的proto上。查看下面显示的屏幕截图:

enter image description here

这意味着存在一个公共内存位置,访问该属性的每个对象都将指向该位置,因此它也具有内存效率。

您可以随时通过直接在对象上定义它来覆盖它来修改该属性:

value.newProp = function(){ console.log("modified property") };

现在,如果你调用这个函数,它将直接在对象上找到它并且不会沿着原型链从公共存储器位置访问它,即function Foo的原型

答案 1 :(得分:1)

简介

由于函数是对象,因此案例1只不过是向对象添加属性。案例2更有趣。请考虑以下代码:

function f (name) {
  this.name = name;
}

f.prototype.sayHello = function () {
  console.log("Hello I'm " + this.name + " !");
};

var x = new f("X");
var y = new f("Y");
<button type="button" onclick="x.sayHello()">x.sayHello()</button>
<button type="button" onclick="y.sayHello()">y.sayHello()</button>

请注意,此代码中没有x.sayHello = function () {...}。想想它两次并问自己:

  

由于x.sayHello从未明确定义,阻止x.sayHello()程序崩溃的基本机制是什么?

这是个问题。

揭开魔力

幸运的是,没有什么神奇的,只有JavaScript内部处理。实际上,当您使用new创建对象时,或者当您调用函数时,在场景后面会发生事件,其中涉及prototype属性。

当您编写new f()时,JavaScript引擎:

  1. 创建一个新对象。
  2. this设置为新对象。
  3. 执行f
  4. 将名为__proto__的属性添加到新对象。
  5. __proto__绑定到f.prototype
  6. 返回新对象。
  7. 当您编写x.sayHello()时,JavaScript引擎:

    1. 查看x
    2. 如果找到sayHello,请转到第6步。
    3. 另外查看x.__proto__
    4. 如果找到sayHello,请转到第6步。
    5. 引发异常并以其他方式退出。
    6. this设置为x
    7. 执行sayHello
    8. 要强调的要点:

      • 当您使用new关键字时,JavaScript会创建一个原型链,即引擎执行以下任务:x.__proto__ = f.prototype
      • 当您尝试调用函数时,JavaScript会通过此原型链执行查找。例如,当您编写x.sayHello()时,如果JavaScript无法在sayHello中找到x,则会查看x.__proto__ f.prototype
      • this的值取决于上下文。例如,当您撰写x.sayHello()时,thisx,当您撰写y.sayHello()时,thisy,当您撰写new f()时1}},this是一个新对象。 More about this

      对于忍者

      自定义实施:

      function instanciate (f, args) {
        var object = {};
        f.apply(object, args);
        object.__proto__ = f.prototype;
        return object;
      }
      
      function execute (object, fName, args) {
        var f = lookup(object, fName);
        if (typeof f !== "function") {
          throw "not a function";
        } else {
          f.apply(object, args);
        }
      }
      
      function lookup (object, key) {
        do {
          if (object.hasOwnProperty(key)) {
            return object[key];
          } else {
            object = object.__proto__;
          }
        }
        while (object !== null);
      }
      
      function f (name) {
        this.name = name;
      }
      
      f.prototype.sayHello = function () {
        console.log("Hello I'm " + this.name + " !");
      };
      
      var x = instanciate(f, ["X"]);
      var y = instanciate(f, ["Y"]);
      <button 
        type="button"
        onclick="execute(x, &quot;sayHello&quot;)"
      >execute(x, "sayHello")</button>
      <button
        type="button"
        onclick="execute(y, &quot;sayHello&quot;)"
      >execute(y, "sayHello")</button>

      旁注

      全局对象并不特别:

      f.prototype.__proto__ = window.__proto__;
      window.__proto__ = f.prototype;
      name = "John Doe";
      sayHello(); // "Hello I'm John Doe !"
      

      相关链接

答案 2 :(得分:0)

  

foo.newProp = function(){...};?

这将定义函数(类)级别的函数。

您可以直接访问它而无需使用对象。

foo.newProp() // call it.
  

foo.prototype.newProp = function(){...};?

它在实例级别定义newPropobject or class instance)。

您需要使用new定义对象,然后才能访问它。

var value = new foo();
value.newProp() // call it

通过使用原型定义函数,可以使所有已经+新定义的对象使用给定的函数