13

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

这是我的示例脚本

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 格式创建函数对象是相等的。

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

干杯

4

2 回答 2

13

prototype属性仅存在于函数上,而person不是函数。这是一个object.

这是正在发生的事情:

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

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

  1. JavaScript 中的一切都是对象,除了原始值(布尔值、数字和字符串)nullundefined.

  2. 所有对象都有一个名为的属性[[proto]],程序员无法访问该属性。然而,大多数引擎使这个属性可以作为__proto__.

  3. 当你创建一个像var o = { a: false, b: "something", ... }then的对象o.__proto__Object.prototype

  4. 当你创建一个像var o = Object.create(something)then的对象o.__proto__something

  5. 当你创建一个像var o = new f(a, b, ...)then的对象o.__proto__f.prototype

  6. 当 JavaScript 找不到属性时,o它会搜索属性 on o.__proto__,然后o.__proto__.__proto__等,直到找到属性或原型链以结尾null(在这种情况下属性为undefined)。

  7. 最后,Object.getPrototypeOf(o)returno.__proto__和 not o.prototype-__proto__存在于包括函数在内的所有对象上,但prototype仅存在于函数上。

于 2013-01-27T07:22:48.103 回答
10

我想你可能会混淆概念。试着先用经典的原型继承来掌握原型的概念,然后你就可以接触到所有的新Object东西了。

在 JavaScript 中,每个对象(数字、字符串、对象、函数、数组、正则表达式、日期... prototype都有.

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

考虑到这一点,您可以扩展原生对象或创建自己的新原型链。这类似于类的概念,但在实践中更强大。

与您的示例类似,您可以编写如下原型链:

// 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 如何在底层工作将有助于真正理解它是如何工作的,而且它在旧浏览器中不起作用。这就是为什么我建议你从经典模式开始,你会在互联网上找到准确而丰富的信息。

于 2013-01-27T07:28:36.100 回答