试图理解JavaScript中原型和构造函数之间的区别
Trying to understand the difference between prototype and constructor in JavaScript
我是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
prototype 是 JS 实现继承的一种方式,因为
Emp(name)
基函数原型被引用到同一个函数本身。是这样吗?employee.constructor
和employee.prototype.constructor
有什么不同?为什么
jack.prototype
undefined
?即如果它继承自函数Emp(name)
为什么它不引用该函数?我怎样才能清楚地预测(无需在控制台中输入(原型或构造函数或原型......收益 率?
如果您习惯于在其他 OOP 语言中轻松扩展对象,那么很难围绕这个概念进行思考,但我会尽力解释这些用途以及是什么。我假设您熟悉其他 OOP 语言。如果我错了,请纠正我。
所有功能都有原型Function()
。他们继承了toString()
和valueOf()
等Function
的所有基本功能。
然后有一个构造函数。这就是你用来初始化对象的东西。
p = new Foo();
所以在这种情况下,我们有两件事。
- 以
Function
为原型的function Foo
(Foo( - 以
Foo()
作为构造函数的Function
对象(p(
(跟着我吗?
Foo()
构造函数可以重写Function
构造函数的某些基本功能,或者保持原样并充分利用它。
如果您熟悉 OOP 原则,原型是基类,构造函数是当前类。在 OOP 中,上述内容将class Foo extends Function
您还可以通过原型和构造函数的整个设置开始继承,在共享功能的同时制作更复杂的对象。
例如:
// Make an 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
}
现在让我们说我们想要不同的方法来baz
离开那里。一个用于控制台日志记录,另一个用于将其放在标题栏上。我们可以对类Foo
做一件大事,但我们不这样做,因为我们需要对为不同实现所做的新类做完全不同的事情。他们唯一需要分享的是baz
物品以及二传手和获取者。
因此,我们需要扩展它以使用 OOP 术语。在 OOO 中,这将是所需的最终结果 class Title extends Foo(){}
.因此,让我们来看看如何到达那里。
function Title(what) {
this.message = what;
}
此时,Title
函数如下所示:
- 原型功能
- 构造函数标题
因此,为了使它扩展Foo
我们需要更改原型。
Title.prototype = new Foo();
- 原型 符
- 构造函数 Foo
这是通过针对原型初始化新的Foo()
对象来完成的。现在它基本上是一个Foo
对象,称为 Title
.这不是我们想要的,因为现在我们无法访问 Title
中的消息部分。我们可以通过将构造函数重置为 Title
来使其正确扩展Foo()
Title.prototype.constructor = Title;
- 原型 符
- 构造函数标题
现在我们又面临一个问题。Foo
的构造函数没有初始化,所以我们最终得到一个未定义的this.baz
要解决这个问题,我们需要打电话给父母。在Java中,你可以用super(vars)
,在PHP $parent->__construct($vars)
中做到这一点。
在 Javascript 中,我们必须修改 Title
类构造函数以调用父对象的构造函数。
所以Title
类构造函数将变为
function Title(what) {
Foo.call(this,what);
this.message = what;
}
通过使用继承Function
对象属性Foo
我们可以初始化Titl
e 对象中的Foo
对象。
现在,您有一个正确继承的对象。
因此,它不像其他OOP语言那样使用extend
关键字,而是使用prototype
和constructor
。
如果你想创建一个javascript对象,你可以简单地声明一个新对象并赋予它属性(我选择物化自己(:
var myself= {
name:"Niddro",
age:32
};
此方法允许您创建一个对象。如果你想要的是一个描述一个人的原型,你可以在其中声明几个具有相同设置的人。若要创建原型,可以使用构造函数,如下所示:
//Constructor
function generalNameForObject(param1, param2,...) {
//Give the object some properties...
}
我想到一个原型(配方(,我想打电话给 person,它应该包含属性名称和年龄,我将使用构造函数来制作它:
function person(name,age) {
this.name=name;
this.age=age;
}
上面的构造函数描述了我的人对象的原型。
通过调用构造函数创建一个新人:
var myself = new person("Niddro",31);
var OP = new person("rajashekar thirumala",23);
一段时间过去了,我意识到我过生日了,所以我需要更改原型的属性:
myself.age=32;
如果要向构造添加属性,则需要手动将其添加到构造函数中:
function person(name,age,rep) {
this.name=name;
this.age=age;
this.reputation=rep;
}
相反,您可以通过执行以下操作向原型添加属性(此处"原型"是一个实际命令,而不仅仅是一个名称(:
function person(name,age,rep) {
this.name=name;
this.age=age;
}
person.prototype.reputation=105;
请注意,这将为所有创建的对象添加信誉 105。
我希望这能让您对构造函数和原型之间的关系有更多的了解。
在JavaScript中,函数employee.constructor//gives Function((
也是对象,可以使用自己的构造函数(即函数(来构造。因此,您可以编写以下代码来获取 Function 的实例。
var employee2 = new Function('a', 'b', 'return a+b');
当您使用函数文字创建函数时也会发生同样的情况,就像您的情况一样。并且此对象的构造函数属性也引用相同的本机函数对象/类。
employee.prototype//给出 Emp {}
JavaScript 中的每个对象都有一个与之关联的原型。虽然只有函数对象原型可以直接通过.prototype
访问。当您使用关键字创建对象时,同一原型将复制到其对象原型new
。此复制主要负责继承/扩展。尽管原型是复制的,但它不像函数对象那样直接可用。它以非标准方式提供,.__proto__
.以下代码将返回 true。
jack.__proto__==employee.prototype
employee.prototype.constructor//give Emp(name(
正如在 Object.prototype.constructor 的文档中所述。这将返回对创建实例原型的 Object 函数的引用。这里引用的对象是 employee.prototype 和 not employee
。这有点复杂,但对象 employee.prototype 的原型是由函数 Emp(name( 创建的
jack.constructor//give Emp(name(
如上一点所述,当您使用新的 Emp(( 创建对象时,此对象原型是由函数 Emp(name( 创建的,
jack.prototype//给出未定义
Jack 不是一个函数对象,所以你不能像那样访问它的原型。您可以像下面这样访问(不是标准方式(插孔的原型。
jack.__proto__
构造函数:
function Foo(x) {
this.x =x;
}
Foo
是构造函数。构造函数是一个函数。
方法可以使用此构造函数Foo
。
"对象是通过在新表达式中使用构造函数创建的;为 例如,new Date(2009,11( 创建一个新的 Date 对象。调用 不使用 new 的构造函数会产生取决于 构造 函数。例如,Date(( 生成一个字符串表示形式 当前日期和时间,而不是对象。
来源 ECMA-262
这意味着如果Foo
返回某些内容(通过return "somevalue";
(,则返回值的类型typeof Foo()
。
另一方面,当您致电时
var o = new Foo();
JavaScript实际上只是这样做
var o = new Object();
o.[[Prototype]] = Foo.prototype;
Foo.call(o);
原型:
当你调用o.a
时,javascript 首先检查a
是否是对象o
的自有属性。如果不是,javascript将查找属性链以查找a
。
有关属性链的更多信息,请查看 mdn。
构造函数的prototype
属性具有非常强大的功能,该功能在类中不可用。如果它有用是另一个争论。构造函数的prototype
属性可以更改链接到其原型链中该原型的每个实例的属性。
TL,DR:
注意:这不是一个确切的定义,摘要的目的只是让您了解构造函数和原型。
如果使用带有 new
关键字的构造函数,则构造函数和原型具有类似的用途,即使它们完全不同。构造函数初始化对象的属性,因此它提供属性。原型还通过属性链(基于原型的继承(提供属性。
原型只是一个对象, 而 构造函数是指向创建对象的函数的指针。
构造函数是一个指针。它指向创建从中检索构造函数的点的 Function((。(即构造函数只是对 Function(( 的引用,我们可以根据需要多次调用它。
构造函数的用途之一是帮助您创建对象的复制副本。由于构造函数属性是对创建对象的函数的引用,因此只要您有该对象的副本,它就会始终指向原始构造函数.https://coderwall.com/p/qjzbig/understanding-constructor-and-prototype
使用对象构造函数:通常,单独创建的对象在许多情况下受到限制。它只创建一个对象。
有时我们喜欢有一个"对象类型",可以用来创建一种类型的许多对象。
创建"对象类型"的标准方法是使用对象构造函数:
function person(first, last, email ) {
this.first_name = first;
this.last_name = last;
this.e_mail = email;
}
var myFather = new person("Ibm", "Muh", "ibm@gmail.com");
上面的函数(人(是一个对象构造函数。拥有对象构造函数后,可以创建相同类型的新对象:
var myFather = new person("Sul", "Ahm", "sul@gmail.com");
每个 JavaScript 对象都有一个原型。原型也是一个对象。
所有 JavaScript 对象都从其原型继承其属性和方法。
对象是使用2种创建对象的方法创建的,即(1(对象文字,或(2(使用新的Object((,继承自名为Object.prototype的原型。使用 new Date(( 创建的对象继承 Date.prototype。
Object.prototype 位于原型链的顶端。
所有 JavaScript 对象(Date、Array、RegExp、Function等(都继承自 Object.prototype.https://www.w3schools.com/js/js_object_prototypes.asp
关键字 prototype 是 Function(( 对象的属性。
原型的值是创建该特定对象的对象构造函数。让我们看几个原型:
Boolean.prototype // returns Object Boolean
String.prototype // returns Object String with methods such as "toUpperCase"
Function.prototype // returns function() {} or function Empty() {}
创建原型:
创建对象原型的标准方法是使用对象构造函数:
function Person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
}
var myFather = new Person("John", "Doe", 50);
使用构造函数,可以使用 new 关键字从同一原型创建新对象,如上所示:
构造函数是 Person 对象的原型。使用大写首字母命名构造函数被认为是一种很好的做法。
向原型添加属性
不能像向现有对象添加新属性一样向原型添加新属性,因为原型不是现有对象。
例:Person.nationality = "English";
若要向原型添加新属性,必须将其添加到构造函数:
function Person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eyecolor;
this.nationality = "English";
}
所有本机和复杂对象都检索到其原始构造函数,在本例中为它们自己。唯一的例外是函数原型,它返回创建它的 Function(( 函数。不要将其与构造函数混淆,因为它是不一样的。
Function.prototype === Function.constructor // returns false, Function.constructor is function Function(){}
还有一个额外的属性 __proto__
,它指的是实例对象的内部 [[proto]] 属性。与 Function(( 对象不同,每个对象都有一个__proto__
。不建议更新实例对象的原型,因为原型并不意味着在运行时更改(您应该能够看到谁是谁的原型,否则您需要花费额外的计算来确保没有循环引用(。
然而事实是,这种方法在许多情况下可能是错误的。在 Javascript 中,当您将方法绑定到 this 关键字时,您只向该特定实例提供该方法,并且它与该构造函数的对象实例没有任何关系,就像静态方法一样。请记住,函数在 Javascript 中是一等公民,我们可以像处理对象一样处理它们,在这种情况下,我们只向函数对象的实例添加一个属性。这只是故事的一部分,您还必须知道,通过它附加的任何方法都将为我们创建的每个新实例重新声明,如果我们希望创建如此多的实例,这可能会对应用程序的内存使用产生负面影响。
- ES6构造函数返回基类的实例
- Jquery在函数之间传递表行
- JS构造函数的原型属性与其原型之间的区别
- 向构造函数或原型添加属性之间的区别
- 试图理解JavaScript中原型和构造函数之间的区别
- javascript中构造函数和对象之间的等价性
- JavaScript中带有构造函数的对象和闭包之间的区别
- Javascript - 这些构造函数之间有什么区别
- 构造函数中的方法与函数的原型属性之间的差异
- 在构造函数内部和外部定义公共方法之间有什么区别吗?
- 构造函数模式和原型模式之间的区别
- 在 JavaScript 中,构造函数和作为构造函数调用的返回对象的函数之间有什么区别
- instanceof和构造函数属性之间的差异
- 什么's使用instanceof和检查构造函数之间的区别
- 不同文件中构造函数之间的部分继承(JavaScript)
- Regex构造函数和字面量之间的反斜杠差异
- Javascript正则表达式字面量和构造函数之间的区别
- javascript构造函数之间的区别
- 构造函数之间的差异
- 在通过构造函数和对象字面语法创建对象之间进行选择