Ein*_*012 45 javascript prototype
我是JavaScript的新手,为了理解这个概念,我已经阅读了许多关于原型和构造函数的文章,但是无论我走到哪里,我都会感到困惑.
当人们同时谈论构造函数和原型时会产生混淆.
在以下示例中
var employee = function Emp(name) {
this.name = name;
}
var jack = new employee("Jack Dwain");
employee.constructor //gives Function()
employee.prototype // gives Emp {}
employee.prototype.constructor //gives Emp(name)
jack.constructor //gives Emp(name)
jack.prototype //gives undefined
Run Code Online (Sandbox Code Playgroud)
原型是JS实现继承的一种方式,因为Emp(name)基本函数原型被引用到同一个函数本身.那是怎么回事?
以什么方式employee.constructor和employee.prototype.constructor不同?
为什么jack.prototype是undefinedie如果它是从函数继承Emp(name)为什么它没有引用该函数?
如何在没有在控制台中输入原型或构造函数或prototype.constructor ......产生的内容的情况下清楚地预测自己
Tsc*_*cka 34
如果你已经习惯了在其他OOP语言中扩展对象的简易性,那么你可以很好地解决这个问题,但是我会尽力解释它们的用途以及它们的用途.我假设您熟悉其他OOP语言.如我错了请纠正我.
所有函数都有原型Function().它们继承了函数中的所有基本函数,如toString()和valueOf().
然后有一个构造函数.这就是你用来初始化一个对象的东西.
p = new Foo();
所以在这种情况下我们有两件事.
function Foo以Function作为原型(美孚)Function带有Foo()构造函数的对象(p)(跟我来?)
该Foo()构造可以覆盖的一些基本功能Function构造,也离开它,因为它是和用好它.
如果您熟悉OOP priciples,那么原型是基类,构造函数是您当前的类.在OOP中,上面会是class Foo extends Function
您还可以使用整个原型和构造函数的设置开始继承,从而在共享功能的同时制作更复杂的对象.
例如:
// make a object initialiser extending Function. in oop `class Foo extends Function`
function Foo(bar) {
this.baz = bar;
}
Foo.prototype.append = function(what) {
this.baz += " " + what;
};
Foo.prototype.get() {
return this.baz
}
Run Code Online (Sandbox Code Playgroud)
现在让我们说我们想要不同的方法让baz离开那里.一个用于控制台日志记录,一个用于将其放在标题栏上.我们可以对我们的类Foo做出很大的贡献,但是我们不这样做,因为我们需要对新类做完全不同的事情,但是为不同的实现做了.他们唯一需要分享的是baz项目以及setter和getter.
所以我们需要扩展它以使用OOP术语.在OOp中,这将是期望的最终结果class Title extends Foo(){}.所以让我们来看看如何到达那里.
function Title(what) {
this.message = what;
}
Run Code Online (Sandbox Code Playgroud)
此时Title函数如下所示:
所以,为了使它扩展到Foo,我们需要改变原型.
Title.prototype = new Foo();
Run Code Online (Sandbox Code Playgroud)
这是通过针对原型初始化新的Foo()对象来完成的.现在它基本上是一个名为Title的Foo对象.这不是我们想要的,因为现在我们无法访问Title中的消息部分.我们可以通过将构造函数重置为Title来使其正确扩展Foo()
Title.prototype.constructor = Title;
Run Code Online (Sandbox Code Playgroud)
现在我们又遇到了一个问题.Foo的构造函数没有初始化,所以最终得到一个未定义的this.baz
要解决这个问题,我们需要调用父级.在java中,你可以super(vars)在php中使用它$parent->__construct($vars).
在javascript中,我们必须修改Title类构造函数以调用父对象的构造函数.
所以Title类构造函数会变成
function Title(what) {
Foo.call(this,what);
this.message = what;
}
Run Code Online (Sandbox Code Playgroud)
通过使用函数对象属性Foo继承,我们可以初始化Title对象中的Foo对象.
现在你有一个正确继承的对象.
因此,extend它不使用像其他OOP语言那样的关键字,而是使用prototype和constructor.
employee.constructor //给出Function()
在JavaScript中,函数也是对象,可以使用自己的构造函数(即Function)构造.因此,您可以编写以下代码来获取Function的实例.
var employee2 = new Function('a', 'b', 'return a+b');
Run Code Online (Sandbox Code Playgroud)
使用函数文字创建函数时也会发生同样的情况.此对象的构造函数属性也引用相同的本机Function对象/类.
employee.prototype //给出Emp {}
JavaScript中的每个对象都有一个与之关联的原型.虽然只有函数对象原型可以直接访问.prototype.当您使用new关键字创建对象时,会在其对象原型上复制相同的原型.这种复制主要负责继承/扩展.虽然复制了原型,但它不像Function对象那样可以直接组合.它以非标准方式提供.__proto__.以下代码将返回true.
jack.__proto__==employee.prototype
Run Code Online (Sandbox Code Playgroud)
employee.prototype.constructor //给出Emp(名字)
正如Object.prototype.constructor的文档中所述.这将返回对创建实例原型的Object函数的引用.这里引用的对象是employee.prototype和not employee.这有点复杂,但对象employee.prototype的原型是由函数Emp(name)创建的
jack.constructor //给出Emp(名字)
如前所述,当您使用新的Emp()创建对象时,此对象原型是由函数Emp(name)创建的,
jack.prototype //给出undefined
jack不是一个函数对象,所以你不能像那样访问它的原型.您可以访问(不是标准方式)插孔原型,如下所示.
jack.__proto__
Run Code Online (Sandbox Code Playgroud)
小智 6
构造函数:
function Foo(x) {
this.x =x;
}
Run Code Online (Sandbox Code Playgroud)
Foo是构造函数。构造函数是一个函数。
有两种方法可以使用此构造函数Foo。
“对象是通过在 new 表达式中使用构造函数创建的;例如,new Date(2009,11) 创建一个新的 Date 对象。在不使用 new 的情况下调用构造函数的后果取决于构造函数。例如,Date() 生成一个字符串表示当前日期和时间而不是对象。”
来源ECMA-262
这意味着如果Foo返回某些内容 (via return "somevalue";),则typeof Foo()是返回值的类型。
另一方面,当你打电话
var o = new Foo();
Run Code Online (Sandbox Code Playgroud)
JavaScript实际上只是做
var o = new Object();
o.[[Prototype]] = Foo.prototype;
Foo.call(o);
Run Code Online (Sandbox Code Playgroud)
原型:
当您调用时o.a,javascript 首先检查是否a是对象的自己的属性o。如果没有,javascript 将查找属性链以找到a.
有关属性链的更多信息,请查看mdn。
prototype构造函数的属性有一个非常强大的特性,这是类中没有的。如果它有用是另一场辩论。该prototype构造的porperty可以改变所有做过链接到原型在他们的原型链实例的属性。
TL,博士:
注意:这不是一个确切的定义,总结的目的只是让您对构造函数和原型有一个感受。
如果您使用带有new关键字的构造函数,则构造函数和原型具有相似的用途,即使它们完全不同。构造函数初始化对象的属性,因此它提供属性。原型还通过属性链(基于原型的继承)提供属性。
如果您想创建一个javascript 对象,则可以简单地声明一个新对象并为其赋予属性(我已选择对自己进行对象化):
var myself= {
name:"Niddro",
age:32
};
Run Code Online (Sandbox Code Playgroud)
此方法使您可以制作一个对象。如果您想要的是一个通常描述一个人的原型,则可以在其中声明具有相同设置的多个人。要创建原型,可以使用构造器,如下所示:
//Constructor
function generalNameForObject(param1, param2,...) {
//Give the object some properties...
}
Run Code Online (Sandbox Code Playgroud)
我想给人打电话一个原型(recepie),它应该包含属性名称和年龄,我将使用构造函数来实现:
function person(name,age) {
this.name=name;
this.age=age;
}
Run Code Online (Sandbox Code Playgroud)
上面的构造函数描述了我的person对象的原型。
通过调用构造函数创建一个新人:
var myself = new person("Niddro",31);
var OP = new person("rajashekar thirumala",23);
Run Code Online (Sandbox Code Playgroud)
过了一段时间,我意识到自己已经过生日了,所以我需要更改原型的属性:
myself.age=32;
Run Code Online (Sandbox Code Playgroud)
如果要向该构造添加属性,则需要手动将其添加到构造函数中:
function person(name,age,rep) {
this.name=name;
this.age=age;
this.reputation=rep;
}
Run Code Online (Sandbox Code Playgroud)
相反,您可以通过执行以下操作为原型添加属性(此处“ prototype”是实际命令,而不仅仅是名称):
function person(name,age,rep) {
this.name=name;
this.age=age;
}
person.prototype.reputation=105;
Run Code Online (Sandbox Code Playgroud)
请注意,这将为所有创建的对象添加105的信誉。
我希望这可以使您对构造函数和原型之间的关系有更多的了解。