【问题标题】:Prototype keyword in JavascriptJavascript 中的原型关键字
【发布时间】:2012-08-21 22:44:10
【问题描述】:

什么是prototype 属性,为什么它是必要的?到目前为止,我了解到这提供了对对象的更多内在和私有prototype 的公共访问;对吗?

另外,下面的语句有什么区别?

MyConstructor.age = 30;
MyConstructor.prototype.age = 30;

简而言之,我需要更好地理解关键字prototype

谢谢

【问题讨论】:

  • 您需要花时间了解更多关于 JavaScript 的信息。 youtube.com/watch?v=v2ifWcnQs6M
  • 这一直困扰着我...我喜欢这个问题
  • 那么任何人都可以解释为什么你有两种方法来创建新属性,即“你可以通过简单地给一个现有对象一个值来添加新属性” person.age=30;和 person.prototype.age = 30;做同样的事情有什么区别
  • Sime:他正在努力学习更多关于 JS 的知识,这就是他(和我)在这里的原因。不是每个人都能从视频中学到很多东西(我当然不会!)

标签: javascript html


【解决方案1】:

“原型”是在对象中发挥作用的东西。

在 Javascript 中,一切都是对象。每个对象都有一个种类,因此继承了那个种类的prototype

例如,取一个简单的数组:var a = []。您可以使用它进行操作,例如a.push(10)。这个push 方法从何而来?来自Array对象的原型,即a

您可以将自己的方法添加到Array 对象,只需在prototype 对象中定义它们即可。例如:

Array.prototype.sortNum = function() {this.sort(function(a, b) {return a - b});};

通过这种方式,您可以使用 all 数组执行类似 a.sortNum() 的操作,甚至是在定义 sortNum 方法之前创建的数组。

(注意:出于兼容性原因,通常不建议扩展原生对象的原型,如Arrays。但这个特殊的例子通常是一个受欢迎的补充,以及像mapforEach这样的规范化方法对于旧版浏览器。)

(只是永远不会扩展Object.prototype!除非您不想弄乱for...in 语句、in 运算符和这类情况。)

如果您想定义自己的类,就像名称 MyConstructor 所暗示的那样,您必须定义其 prototype 来定义该类的所有实例的方法:

function MyConstructor(name) {this.name = name};
MyConstructor.prototype = {
    print: function() {return this.name;}
};

var mc = new MyConstructor("foo");
alert(mc.print()); // alerts "foo"

您也可以在 prototypes 中定义更多的函数:

MyConstructor.prototype.age = 30;

alert(mc.age); // alerts 30

在定义“默认”对象值时要小心,因为更改它可能会导致该类的所有个实例发生变化。

但这很方便Object.defineProperty:

Object.defineProperty(MyConstructor.prototype, "wholeString", {
    get: function() {return this.name + "=" + this.age;},
    set: function(v) {this.name = v.substring(3);}
});

alert(mc.wholeString); // alerts "foo = 30"

(不幸的是,IE

当您改为定义MyConstructor.age = 30 时,您实际上是在定义函数 MyConstructor 的成员,因此mc.age 将是未定义的。 MyConstructor 的每个实例都继承了MyConstructor.prototype 中定义的方法和成员,而不是函数MyConstructor 的方法和成员。

其实还有很多话要说。对象可以是另一个类的子类,因此也继承了超类的prototype。例如,document.bodyHTMLBodyElement 的一个实例,它是HTMLElement 的子类,Element 的子类等等,直到你得到Object 作为最上面的超类。所以,document.body继承了HTMLBodyElementHTMLElementElementObject原型中定义的所有方法。这称为原型链。

对自定义对象做同样的事情有点棘手:

function Class() {};
Class.prototype.foo = function() {alert("foo");};

function Subclass() {};
Subclass.prototype = new Class();
Subclass.prototype.bar = function() {alert("bar");};

var a = new Class(), b = new Subclass();
a.foo(); // alerts"foo"
a.bar(); // throws an error
b.foo(); // alerts "foo"
b.bar(); // alerts "bar"

a instanceof Class;    // true
a instanceof Subclass; // false
b instanceof Class;    // true
b instanceof Subclass; // true

【讨论】:

  • awesome explantion... 你能指导我了解有关面向对象 javascript 的详尽教程吗 - 我最终将使用它在运行时为我的工作生成 html5 控件(和扩展控件)。 . Douglas Crockford 的 tuorials 真的不是那么有概念,E John 的幻灯片也缺乏解释......谢谢......
  • @user503510 Gee、Crockford 和 Resig 是两个主要的 Javascript 大师。每个 Javascript 程序员都从他们身上学到了一些东西。你可以试试MDN article关于OOP编程或者JavascriptKit的那个。
【解决方案2】:

在 JavaScript 中,函数对象有一个内置的 .prototype 属性。该属性的值是一个对象。如果函数用作构造函数,则生成的实例继承自该“原型”对象。

例子:

var Dog = function () {}; // the constructor function

Dog.prototype.bark = function () {}; // adding a method to Dog.prototype

var dog1 = new Dog; // creating a new instance

dog1.bark(); // the instance inherits the "bark" method from Dog.prototype

请注意,.prototype 属性(函数对象)与[[Prototype]] 内部属性不同。所有对象都包含后者。它是对对象原型的内部引用。 (在上面的例子中,dog1 对象的[[Prototype]] 指的是Dog.prototype。)另一方面,只有函数对象具有内置的.prototype 属性(这是有道理的,因为只有函数对象可以用作构造函数)。

【讨论】:

  • 这也很好地解释了它(谢谢),但我需要选择最上面的作为答案 - 它更详细并且还解释了其他事情......
  • 又短又甜:)
【解决方案3】:
var foo = function () {};
foo.bar = 5;
foo.prototype.foobar = 10;

var x = new foo();
x.bar; // undefined
x.foobar; // 10

编辑:另外,你可以这样做

foo.prototype.foobar = 20;
x.foobar; // 20

【讨论】:

    猜你喜欢
    • 2017-02-16
    • 2015-08-25
    • 2018-11-17
    • 1970-01-01
    • 1970-01-01
    • 2012-10-24
    • 1970-01-01
    • 2016-02-25
    • 2010-09-27
    相关资源
    最近更新 更多