【问题标题】:javascript prototype value in constructer and literal declaration构造函数和文字声明中的javascript原型值
【发布时间】:2014-03-16 14:34:02
【问题描述】:

1

 function Student() {
    // initialization
    }

2

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

如果是 1 和 2,原型值是多少。谢谢。

第一种情况我得到Student,第二种情况我得到Object。为什么?

【问题讨论】:

  • 两种声明构造函数的方式是等价的。两个构造函数都有一个默认的原型对象。
  • 您究竟是如何从他们那里获得StudentObject 的?你的测试是什么?并且,请注意,第二个示例是一个引用但匿名的构造函数。 var Student = function Student() {}; 也会给它命名。
  • var functionName = function() {} vs function functionName() {} 的可能副本。原型没有区别。
  • @JonathanLonowski 我将console.log(Object.getPrototypeOf(new Student())); 放在 google chrome 的 javascript 控制台中。
  • @Bergi 它不是重复的。我在问这两个prototype 有何不同。请再考虑。谢谢。

标签: javascript oop


【解决方案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. 按照 8.12 中的描述设置 F 的所有内部方法,除了 [[Get]] 之外。
  3. 将 F 的 [[Class]] 内部属性设置为“Function”。
  4. 将 F 的 [[Prototype]] 内部属性设置为 15.3.3.1 中指定的标准内置函数原型对象。
  5. ...

按照标准:

产生式 ObjectLiteral : { } 评估如下:

返回一个新对象,就像由表达式 new Object() 创建的,其中 Object 是具有该名称的标准内置构造函数。

这意味着当使用{} 时,内部应调用new Object,这意味着您将拥有Object 作为默认原型(参见上面的参考)。

【讨论】:

  • 只做Student.prototype不是更简单吗?毕竟这是实例将要获得的原型,不是吗?
  • 是的,基本上是一样的,但是我相信通过指向对象实例的原型来展示不同的原型会更容易。
  • 对于第一种情况,我得到的是学生,而对于第二种情况,我得到的是对象。为什么?
  • student.prop = 'val' 是关于什么的?
  • 在第一种情况下,Object.getPrototypeOf(s) 将等于Student.prototype,正如上面提到的@EdwinDalorzo。
【解决方案2】:

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


不同的是,第二个例子是匿名构造函数。

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

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

var Student 没有 name 它,只引用它。但是,它也可以命名:

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

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

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"

【讨论】:

    【解决方案3】:

    有很多材料可以解释原型的工作原理。在上面的示例中,您声明了两个等效的构造函数。也就是说,您可以从您的两个构造函数中创建“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 的原型是另一个对象。

    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 对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-04
      • 1970-01-01
      • 2016-01-07
      • 2013-04-05
      • 1970-01-01
      • 2014-01-01
      • 2017-08-21
      相关资源
      最近更新 更多