Javascript对象&原型

时间:2016-06-23 18:24:09

标签: javascript object prototype

我是Javascript的新手并且对以下陈述的结果感到困惑。你能帮助澄清每个结果背后的原因吗?如果您还可以建议明确解释这些情况下预期行为的资源,将不胜感激。

function Person(){
   this.a = function(){alert("a")};
}

Person.prototype.b = function(){alert("b")};
Person.c=function(){alert("c")};

var test = new Person();
test.a(); // works
test.b(); // works
test.prototype.b(); //error

Person.prototype.a(); // error (why?)
Person.prototype.b(); //works (why?)

Person.c(); //works

Person();
Person.a(); /* error (Person() call should have set this.a 
               on the Person object just like the c method, 
               why doesn’t it work?) */

Person.b();//error (why?)

5 个答案:

答案 0 :(得分:1)

我对这是否重复存在两种看法,或者是否应该将它分解为几个不同的问题。然而,由于这吸引了可疑质量的答案,让我们逐行浏览你的代码。

function Person(){
   this.a = function(){alert("a")};
}

定义函数Person。没什么特别的。调用它Person()将取决于它是否以严格模式运行,抛出错误'无法设置属性" a"未定义的'或者它会创建一个全局变量' a' vaue是一个警告' a'。

的功能

但是,按照惯例,Javascript中的大写函数应该是构造函数,并使用new运算符调用。致电new Person()会为你带来一些魔力。它创建一个新对象并将其设置为构造函数中的this值。构造函数也隐式返回新对象,这就是它没有return语句的原因。这意味着新人有一种方法,可以提醒他们注意一个'什么时候叫。

但实际上很少这样做,使用原型更为常见。 new运算符还将新创建的对象的内部原型设置为构造函数的.prototype属性的值(该对象实际上没有.prototype {{1} 1}}属性)。构造函数.prototype对象上定义的任何内容都可用于通过使用new调用该构造函数创建的每个实例。

Person.prototype.b = function(){alert("b")};

这定义了Person(构造函数)的.prototype对象上的函数b。它将通过调用new Person()提供给所有创建的Person实例。它也可以直接调用Person.prototype.b()。这种方法比用于附加' a'方法,因为所有的人都分享了' b'但他们都有自己的副本' a'。

Person.c=function(){alert("c")};

在Javascript 中,是一个对象,包括函数。对象可以分配属性。在这里,您将为Person函数本身的c属性分配一个函数。如果您习惯使用基于类的语言,则类似于类静态方法。

希望到现在为止,其余部分将变得更加清晰。每个人都包括'测试'会有一个' a'方法,因为构造函数分配它。但是,人的原型没有' a'方法,它只是在构造函数中赋值。人的原型有一个''方法,意味着所有Person实例都可以访问该共享的' b'方法。 Person函数本身有一个' c'方法,但它没有传递给实例,所以'测试'没有' c'方法

答案 1 :(得分:1)

好的,我会试一试。我很快就会采访,所以这是一个很好的做法:)

function Person(){
   this.a = function(){alert("a")};
}

Person.prototype.b = function(){alert("b")};
Person.c=function(){alert("c")};

var test = new Person();
test.a(); // works
test.b(); // works
test.prototype.b(); //error

听起来你有这个,但test是一个对象,而不是构造函数。它没有原型键。

Person.prototype.a(); // error (why?)
Person.prototype.b(); //works (why?)

在这里,事情变得有趣。查看Person()函数;所有它确实引用传递给它的参数并返回一个新对象。看起来并不复杂。然而,这是JavaScript疯狂的原型继承发挥作用的地方。

假设您在String上编写了一个更高级别的原型方法,如String.prototype.capitalize = function()...,并且该方法将字符串大写。您创建的每个新字符串都有capitalize()方法,但它不像字符串是一个带有该方法键的对象。

这与Person.prototype.a()Person.prototype.b()正在做的事情相同。通过Person()函数运行对象会创建一个包含这些键的对象。由于Person()构造函数只返回一个键为a的对象,因此到目前为止这是test的样子:

console.log(test); // {a: [Function]}

但为什么test.b()有效?这是因为构造函数创建的任何对象都继承了构造函数 .prototype 上的所有属性。向原型中添加内容并不会更改添加到构造对象的键,而是让其构造的对象可以访问它。在某事物上调用方法首先会查看它的键,然后是构造函数的隐藏[[prototype]]值,然后是它的父级,依此类推。您可以在Chrome中的console.log中看到这一点。

Person();
Person.a(); /* error (Person() call should have set this.a 
               on the Person object just like the c method, 
               why doesn’t it work?) */

Person.b();//error (why?)

这里的错误是Person()是一个对象。不是;它是一个功能。构造函数中的this引用引用传递给它的对象;这意味着它被设置为的变量。由于我们只是调用Person()而未将结果设置为任何内容,因此this未定义且Person()的结果未定义,因为没有任何内容可以返回。函数不能有密钥或方法。

希望我能提供帮助。这对我来说也是很好的做法!

答案 2 :(得分:0)

执行Person.c = ...时,您需要设置静态属性,因此它们不属于原型。

稍后,您尝试将原型方法调用到构造函数,并且它们不存在,因为原型是该构造函数的实例的蓝图。

答案 3 :(得分:0)

class.prototype就像对象和你的类之间的链接。 class.prototype您可以分配将在您的类的所有实例之间共享的函数和属性,以及调用函数将在prototype

class对象上查找的函数和属性

//所以你可以在这里调用原型

Person.prototype.fun;

//但是你直接调用func

test.fun

MDN

答案 4 :(得分:0)

我会尽力向您解释,但英语不是我的主要语言。如果您有任何具体问题,请在评论部分询问我,我会详细说明。要完整理解,请阅读more here

test.a(); // works -> Yes because it accessing the property that exists in  Person it self
test.b(); // works ->First It will look into test instance properties if it doesn't find it will look one level up into the Person prototype object and it will find it there.

test.prototype.b(); //error because test is an instance and instances do not have a prototype property.

Person.prototype.a(); // error (why?) Because you are going to look for a property a inside Person prototype which does not have it. Property lookup goes only forward not backward. 
Person.prototype.b(); //works (why?) because b is a property of the Person prototype. 
//typeof Person.prototype is object same as var prototype={} than prototype.b=function(){} so now you can call prototype.b();

Person.c(); //works c is 'static' (more like object literal property assignment because every function in js still is an object) property of Person  same as var Person2={};Person2.c=function(){}; that is why you can access it without needing to initialize Person. 

Person();
Person.a(); /* error (Person() call should have set this.a 
                           on the Person object just like the c method, 
                           why doesn’t it work?) */ That property requires you to create an instance of Person.

Person.b();//error (why?)  it is the same as a but b is a property of prototype of Person