关于javascript:为什么原型未定义

why prototype is undefined

我知道这个问题已经被问过数百遍了,但是,我似乎无法理解prototype

的概念

这是我的示例脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var config = {
  writable: true,
  enumerable: true,
  configurable: true
};

var defineProperty = function(obj, name, value) {
  config.value = value;
  Object.defineProperty(obj, name, config);
}


var man= Object.create(null);
defineProperty(man, 'sex',"male");

var person = Object.create(man);
person.greet = function (person) {
    return this.name + ': Why, hello there, ' + person + '.'
}
var p=Object.getPrototypeOf(person);
alert(p.sex);//shows male
person.prototype.age=13;//why there is a error said the prototype is undefined? I thought it supposed be man object...

var child=function(){}
child.prototype.color="red";//why this line doesn't show error? both child and person are an object .

alert(child.prototype.color);//shows red

var ch=Object.getPrototypeOf(child);

alert(ch.color);//why it is undefined? it is supposed red.

希望您能给我一些帮助...谢谢。

已更新:

感谢大家的帮助,根据Elclanrs的回答,以下是我所学到的知识。

Function是javascript中的内置对象之一。 3种格式创建函数对象相等。

1
2
3
4
5
6
7
8
9
var function_name = new Function(arg1, arg2, ..., argN, function_body)
function function_name(arg1, arg2, ..., argN)
{
...
}
var function_name=function(arg1, arg2, ..., argN)
{
...
}

因此,这就是为什么创建原型链的原因,我们必须创建一个函数,然后使用new关键字调用它。

Function.prototype是对所有功能对象prototype的引用。

干杯


prototype属性仅存在于函数中,而person不是函数。这是object

这是正在发生的事情:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var man = Object.create(null);         // man (object) -> null
man.sex ="male";

var person = Object.create(man);       // person (object) -> man (object) -> null
person.greet = function () { ... };

var p = Object.getPrototypeOf(person); // man (object) -> null
alert(p.sex);                          // p is the same object as man

person.prototype.age = 13;             // person doesn't have a prototype

var child = function () {};            // child (function) -> Function.prototype
                                       // -> Object.prototype -> null
child.prototype.color ="red";         // child has a prototype

var ch = Object.getPrototypeOf(child); // Function.prototype

alert(ch.color);                       // ch is not the same as color.prototype
                                       // ch is Function.prototype

有关更多信息,我建议您阅读以下答案:https://stackoverflow.com/a/8096017/783743

编辑:用尽可能少的词来解释正在发生的事情:

  • 除了原始值(布尔值,数字和字符串)以及nullundefined,JavaScript中的所有对象都是对象。

  • 所有对象都有一个名为[[proto]]的属性,程序员无法访问该属性。但是,大多数引擎使此属性可作为__proto__

    访问。

  • 当创建类似var o = { a: false, b:"something", ... }的对象时,o.__proto__Object.prototype

  • 当创建类似var o = Object.create(something)的对象时,o.__proto__something

  • 创建类似var o = new f(a, b, ...)的对象时,o.__proto__f.prototype

  • 当JavaScript在o上找不到属性时,它将搜索o.__proto__上的属性,然后依次搜索o.__proto__.__proto__等,直到找到该属性或原型链以null结尾(在这种情况下)属性是undefined)。

  • 最后,Object.getPrototypeOf(o)返回o.__proto__而不是o.prototype-__proto__存在于包括函数在内的所有对象上,但prototype仅存在于函数上。


  • 我认为您可能会混淆一些概念。首先尝试通过经典的原型继承来掌握原型的概念,然后就可以使用所有新的object内容。

    在JavaScript中,每个对象(数字,字符串,对象,函数,数组,正则表达式,日期...)都有一个prototype,您可以将其视为当前所有方法(函数)的集合以及该对象的未来实例。

    要创建原型链,必须创建一个函数,然后使用new关键字调用它以指定它是构造函数。您可以将构造函数视为主要函数,该函数采用构建对象新实例所需的参数。

    请记住,您可以扩展本机对象或创建自己的新原型链。这类似于类的概念,但在实践中功能更强大。

    类似于您的示例,您可以编写这样的原型链:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    // Very basic helper to extend prototypes of objects
    // I'm attaching this method to the Function prototype
    // so it'll be available for every function
    Function.prototype.inherits = function(parent) {
      this.prototype = Object.create(parent.prototype);
    }

    // Person constructor
    function Person(name, age, sex) {
      // Common to all Persons
      this.name = name;
      this.age = age;
      this.sex = sex;
    }

    Person.prototype = {
      // common to all Persons
      say: function(words) {
        return this.name +'says: '+ words;
      }
    };

    // Student constructor  
    function Student(name, age, sex, school) {
      // Set the variables on the parent object Person
      // using Student as a context.
      // This is similar to what other laguanges call 'super'
      Person.call(this, name, age, sex);
      this.school = school; // unique to Student
    }

    Student.inherits(Person); // inherit the prototype of Person

    var mike = new Student('Mike', 25, 'male', 'Downtown'); // create new student

    console.log(mike.say('hello world')); //=>"Mike says: hello world"

    在更新版本的JavaScript(阅读EcmaScript)中,他们添加了处理对象并扩展对象的新方法。但是它的概念与经典原型继承有点不同,它看起来更复杂,并且对JS底层如何工作有更多的了解将有助于真正了解它的工作原理,而且它不适用于旧版浏览器。这就是为什么我建议您从经典模式开始的原因,您可以在互联网上找到准确而丰富的信息。