构造函数和文字声明中的javascript原型值

时间:2014-03-16 14:34:02

标签: javascript oop

1

 function Student() {
    // initialization
    }

2

var student = function(){
// initialization
};

在1和2的情况下,原型值是多少。谢谢。

第一个案例我得到Student而第二个案件我得到Object。为什么呢?

3 个答案:

答案 0 :(得分:1)

您可以通过以下方式轻松查看对象的原型:

var s = new Student();
Object.getPrototypeOf(s);

Object.getPrototypeOf(student);

在第一种情况下(构造函数),您可以通过以下方式更改默认原型值:

Student.prototype = { foo: 'bar' };
var s = new Student();
Object.getPrototypeOf(s); // { foo: 'bar' }

在第二种情况下:

var student = Object.create({ foo: 'bar' });
student.prop = 'val';
Object.getPrototypeOf(student); // { foo: 'bar' }

为什么他们不同?

您可以使用构造函数here查看用于创建对象的确切算法。 基本上是:

  
      
  1. 创建一个新的本机ECMAScript对象,让F成为该对象。
  2.   
  3. 按照8.12中的说明设置F的[[Get]]除外的所有内部方法。
  4.   
  5. 将F的[[Class]]内部属性设置为“Function”。
  6.   
  7. 将F的[[Prototype]]内部属性设置为15.3.3.1中指定的标准内置函数原型对象。
  8.   
  9. ...
  10.   

根据标准:

  

生产ObjectLiteral:{}的计算方法如下:

     

返回一个新对象,就好像通过表达式new Object()一样   Object是具有该名称的标准内置构造函数。

这意味着当使用{}时,内部应该被称为new Object,这意味着您将Object作为默认原型(请参阅上面的参考资料)。

答案 1 :(得分:1)

  

我将console.log(Object.getPrototypeOf(new Student()));放入谷歌浏览器的javascript控制台。


不同之处在于第二个示例是匿名构造函数。

function Student() {}
console.log(Student.name); // "Student"

var Student = function () {};
console.log(Student.name); // ""

var Studentname,仅引用它。但是,它也可以命名:

var Student = function Student() {};=
console.log(Student.name); // "Student"

无论如何,每个实例仍被识别为Student s:

console.log(new Student() instanceof Student); // true for both

但是,Chrome正在尝试提供更多信息,因此它会跟随prototype链,直到找到可以显示的name

var Student = function () {};

var base = Object.getPrototypeOf(Student.prototype);

console.log(base.constructor === Object); // true
console.log(base.constructor.name);       // "Object"

答案 2 :(得分:0)

有很多材料可以解释原型的工作原理。在上面的示例中,您声明了两个等效的构造函数。也就是说,您可以从两个构造函数中创建“Student”类型的对象。

例如,我可以这样做:

function Student() {
    // initialization
}
var pascal = new Student();

或者我能做到

var Student = function(){
// initialization
};
var pascal = new Student();

结果是一样的。

现在,这些构造函数有一个原型对象。如果您没有为其分配一个,则默认情况下会获得一个。例如,在任何一种情况下我都可以这样做:

Student.prototype.getName = function(){
  return this.name;
};

然后我的任何学生实例都可以这样:

pascal.getName();

但是,您可以创建自己的原型对象并直接分配它们,以防您希望通过它们将某些内容暴露给给定构造函数的所有实例。例如。

你可以说学生的原型是另一个对象。

Student.prototype = {
   takeExam: function(){
      //define take exam
   },
   constructor: Student
};

现在这个合成对象是Student构造函数的原型。

或者您甚至可以使用此定义类型层次结构,如下例所示:

function FlyingThing(){ };

FlyingThing.prototype.fly = function(){
   //fly
};

function Bird(){ }

Bird.prototype = new FlyingThing();
Bird.prototype.walk = function(){
  //walk
};

现在,Bird的每个例子都可以飞行和行走。

现在,区分构造函数原型和实例原型非常重要。正如我已经展示的那样,您可以直接访问构造函数原型,您可以轻松地更改它,向其中添加新内容,或者在您认为合适的情况下进行更改。

为给定的构造函数创建实例时,会根据您用于创建它的构造函数为其分配一个原型对象。那个原型不是那么容易获得的。该原型是JavaScript将在属性查找中使用的原型。

如果您想知道给定实例对象的原型是什么,则需要使用Object.getPrototypeOfObject.isPrototypeOf方法,如其他答案所示。

Student实例的原型在逻辑上应该是您为Student构造函数定义的Student.prototype对象。