在JavaScript中使用'prototype'与'this'?

在JavaScript中使用'prototype'与'this'?

有什么区别

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

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


叮当猫咪
浏览 612回答 4
4回答

拉风的咖菲猫

拿这两个例子:var A = function() { this.hey = function() { alert('from A') } };与var A = function() {}A.prototype.hey = function() { alert('from prototype') };这里的大多数人(特别是评价最高的答案)试图解释他们是如何不同的,而不解释为什么。我认为这是错误的,如果你先了解基本面,那么差异就会变得明显。让我们先尝试解释一下基本面......a)函数是JavaScript中的对象。JavaScript中的每个对象都有一个内部属性(意思是,你不能像其他属性那样访问它,除了可能在像Chrome这样的浏览器中),通常被称为__proto__(你实际上可以输入anyObject.__proto__Chrome来查看它所引用的内容。这就是那个一个属性,仅此而已.JavaScript中的属性=对象内部的变量,仅此而已。变量做什么?它们指向事物。那么这个__proto__属性指向什么?好吧,通常是另一个对象(我们将在后面解释原因)。强制JavaScript使__proto__属性不指向另一个对象的唯一方法是使用var newObj = Object.create(null)。即使你这样做,__proto__属性STILL作为对象的属性存在,只是它不指向另一个对象,它指向null。这是大多数人感到困惑的地方:当你在JavaScript中创建一个新函数时(也是一个对象,记得吗?),当它被定义时,JavaScript会自动在该函数上创建一个名为的新属性prototype。试试吧:var A = [];A.prototype // undefinedA = function() {}A.prototype // {} // got created when function() {} was definedA.prototype与酒店完全不同__proto__。在我们的例子中,'A'现在有两个叫做'prototype'的属性__proto__。这对人们来说是一个很大的混乱。prototype和__proto__属性没有任何关系,它们是指向不同值的单独事物。您可能想知道:为什么JavaScript __proto__在每个对象上都创建了属性?嗯,一个字:代表团。当您在对象上调用属性并且该对象没有它时,JavaScript会查找引用的对象__proto__以查看它是否具有该对象。如果它没有它,那么它会查看该对象的__proto__属性等等......直到链结束。因此名称原型链。当然,如果__proto__没有指向一个对象,而是指向null,运气好,JavaScript意识到并将返回您undefined的属性。您可能还想知道,为什么JavaScript prototype在定义函数时会创建一个函数调用属性?因为它试图愚弄你,是的,愚弄你,它就像基于类的语言一样。让我们继续我们的例子并创建一个“对象” A:var a1 = new A();当事情发生时,背景中会发生一些事情。a1是一个普通的变量,它被赋予了一个新的空对象。new在函数调用之前使用运算符的事实A()在后台执行了一些附加操作。该new关键字创建一个新的对象现在引用a1和对象为空。这是另外发生的事情:我们说过,在每个函数定义中创建了一个名为prototype(可以访问它,与__proto__属性不同)创建的新属性?那么,这个属性现在正在使用。所以我们现在处于一个新鲜出炉的空a1物体的位置。我们说JavaScript中的所有对象都有一个内部__proto__属性,指向某个东西(a1也有它),无论它是null还是其他对象。什么是new运营商做的是,它设置一个__proto__属性指向函数的prototype性质。再读一遍。它基本上是这样的:a1.__proto__ = A.prototype;我们说这A.prototype只不过是一个空对象(除非我们在定义之前将其更改为其他内容a1)。所以现在基本上a1.__proto__指向同一个东西A.prototype,这就是空对象。它们都指向此行发生时创建的同一对象:A = function() {} // JS: cool. let's also create A.prototype pointing to empty {}现在,var a1 = new A()处理语句时还会发生另一件事。基本上A()是执行,如果A是这样的:var A = function() { this.hey = function() { alert('from A') } };里面的所有东西function() { }都将被执行。当你到达该this.hey..行时,this改为a1,你得到这个:a1.hey = function() { alert('from A') }我不会介绍为什么要进行this更改,a1但这是了解更多内容的好方法。总而言之,当你做的var a1 = new A()时候,背景中发生了三件事:创建并分配一个全新的空对象a1。a1 = {}a1.__proto__属性被指定指向与指向相同的东西A.prototype(另一个空对象{})该函数A()正在执行时this设置为在步骤1中创建的新的空对象(请阅读上面引用的答案,了解为什么要this更改a1)现在,让我们尝试创建另一个对象:var a2 = new A();步骤1,2,3将重复。你注意到了什么吗?关键词是重复。第1步:a2将是一个新的空对象,第2步:它的__proto__属性将指向同一个东西A.prototype指向,最重要的是,第3步:函数A()是AGAIN执行的,这意味着a2将获取hey包含函数的属性。a1并a2有两个名为SEPARATE的属性hey,指向2个SEPARATE函数!我们现在在相同的两个不同的对象中有重复的函数做同样的事情,oops ...你可以想象如果我们有1000个对象创建的内存含义new A,在所有函数声明占用的内存比数字2之类的东西更多。所以我们该如何防止这种情况?还记得为什么__proto__属性存在于每个对象上?因此,如果您检索yoMan属性a1(不存在),__proto__将查询其属性,如果它是一个对象(大多数情况下是),它将检查它是否包含yoMan,如果不包含,它会查询该对象的__proto__等等。如果是,它将采用该属性值并显示给您。所以有人决定使用这个事实+当你创建时a1,它的__proto__属性指向同一个(空)对象A.prototype指向并执行此操作:var A = function() {}A.prototype.hey = function() { alert('from prototype') };凉!现在,当你创建时a1,它再次经历了上面的所有3个步骤,并且在步骤3中,它没有做任何事情,因为function A()没有任何东西可以执行。如果我们这样做:a1.hey它会看到它a1不包含hey,它会检查它的__proto__属性对象,看它是否有它,就是这种情况。通过这种方法,我们消除了步骤3中的部分,其中在每个新对象创建时复制了函数。相反的a1,并a2具有独立的hey财产,现在他们没有了它。我想,你现在已经弄明白了。那是很好的事情......如果你了解__proto__和Function.prototype,像这些问题将是非常明显的。注意:有些人往往不会调用内部的Prototype属性,因为__proto__我在帖子中使用了这个名称,将它与Functional.prototype属性区分开来,作为两个不同的东西。

侃侃无极

在大多数情况下,它们本质上是相同的,但第二个版本节省了内存,因为只有一个函数实例而不是每个对象的单独函数。使用第一种形式的原因是访问“私人成员”。例如:var A = function () {     var private_var = ...;     this.x = function () {         return private_var;     };     this.setX = function (new_x) {         private_var = new_x;     };};由于javascript的作用域规则,private_var可用于分配给this.x的函数,但不在对象之外。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript