我正在为初学者阅读MDN Javascript,并且它说你可以创建一个构造函数,然后根据该构造函数创建对象实例。现在,您可以访问构造函数中定义的属性和方法。然而,他们接着说,只有构造函数原型属性上定义的属性和方法才可用于对象实例,至少我理解。有人可以清除这一点,因为实例似乎可以访问这些实例,并且示例中没有定义原型属性。谢谢
function Person(first, last, age, gender, interests) {
this.name = {
first,
last
};
this.age = age;
this.gender = gender;
this.interests = interests;
this.bio = function() {
alert(this.name.first + ' ' + this.name.last +
' is ' + this.age + ' years old.'+
' He likes ' + this.interests[0] +
' and ' + this.interests[1] + '.');
};
this.greeting = function() {
alert('Hi! I\'m ' + this.name.first + '.');
};
}
var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);
person1['age']
person1.interests[1]
person1.bio()
// etc.
答案 0 :(得分:3)
附加到构造函数的prototype
属性的任何内容都是使用构造函数创建的所有实例之间的共享。所有这些对象的值都相同。
构造函数还可以将单个属性附加到正在创建的对象。这些特定于新实例,不会共享。
答案 1 :(得分:2)
因此,Javascript对象的工作方式与其他编程语言不同。好吧,无论如何,大多数主流的。
这里的交易 - 一个Javascript对象实际上只是一个字典(又名地图)。例如:
var x = {}; // creates a new blank object
x.something = 42; // creates a property on the object and assigns value to it
x['something'] = 15; // Alternate syntax. Assigns to the same property we just created.
x['yo, this is valid too!'] = true; // Yes, this is valid too.
明白我的意思?它只是一本字典,你可以设置你想要的任何东西。并且也没有设置 - 这是delete
运算符的作用。
那么那些构造函数和原型呢?好吧,任何函数都可以用作构造函数。当你去的时候
var x = new foo();
真正发生的是Javascript创建一个新的空白对象,然后在将新创建的对象放入foo()
时调用this
。而且,看起来它有点像构造函数。
实际上有一点需要提及的怪癖。如果构造函数return
是一个值,那么Javascript使用它而不是新创建的对象。所以,如果你这样做:
function foo() {
this.meaning = 42;
}
var a = new foo();
然后a
将包含Javascript为您创建的空白对象。但如果你这样做:
function foo() {
this.meaning = 42;
return {nope: 3};
}
var a = new foo();
然后a
将包含{nope : 3}
对象。好的,但很少使用。
无论如何,我们在哪里?啊,是的,原型。哦,等等,首先需要解释另一件事。在Javascript 一切是一个对象。所以,就像这些事情完全有效:
var a = 42;
var b = "hello, world";
a.foo = "yay";
b.bar = 10;
而且,只是为了真正打动你的想法,功能也是对象。一流的公民,可以这么说。这都是有效的:
function foo() {
}
foo.bar = "baz";
var x = foo;
是的,您可以像处理任何其他对象一样处理函数。您可以将它们放在变量中,将它们传递给参数中的其他函数,为它们分配和删除任意属性,然后命名它们。这是其他语言中很少见到的功能,所以它可能是最难解决的问题。我知道当我第一次明白这一点时,我的思绪就被吹了。
现在我们可以谈论原型。你看,Javascript中的每个函数都有一个叫做prototype
的特殊魔法属性。默认情况下,它设置为空白对象。但您可以将其设置为另一个对象。或者,您可以向现有空白对象添加/删除属性。它只是另一个对象,没什么好看的。
此外,Javascript中的每个对象都有一个名为__proto__
的特殊魔法属性。请记住,当您致电new foo()
时,会创建一个新对象并将其作为foo()
传递给this
?好吧,那个新对象的__proto__
设置为当时的foo.prototype
。
现在假设你这样做:
function foo() {
this.a = 42;
}
foo.prototype.b = 15;
var x = new foo();
如果您输入x.a
,那么x
就有这样的属性,一切都很好。但是,如果您输入x.b
,那么x
就没有这样的属性,而且这就是魔术发生的地方。 Javascript会自动检查是否有x.__proto__.b
,如果有,则返回!如果没有,它会检查x.__proto__.__proto__.b
等,直到它遇到__proto__ == null
的对象,然后它放弃并返回undefined
,因为没有这样的属性。
另一方面,当你现在这样做时:
x.b = "foobarbaz";
然后直接在b
对象上创建x
属性。原型保持不变。
这就是你如何创造"继承"在Javascript中。随着原型。它与典型的基于类的语言不同,但同样强大。
还有一些其他的细微差别和技巧可以提及,还有大量的例子可以帮助你理清这一切,但是......我今天已经没有果汁了。 :)这应该回答这个问题,并希望能更好地理解你正在阅读的其他教程。
答案 2 :(得分:0)
Jules是对的。
进一步详细说明: 你有这个构造函数。
function Person(first, last, age, gender, interests) {
this.name = {
first,
last
};
this.age = age;
this.gender = gender;
this.interests = interests;
this.bio = function() {
alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
};
this.greeting = function() {
alert('Hi! I\'m ' + this.name.first + '.');
};
}
现在你可以创建它的实例......
var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);
var person2 = new Person('Anne', 'Smith', 32, 'male', ['music', 'skiing']);
如果您访问原型并更改它,则每个其他实例也会进行此更改。
person1.__proto__.attrX = "Hello World"
alert(person2.attX)
所有这些Javascript原型继承起初可能会非常混乱,但实际上你几乎从不需要。我实际上甚至不推荐它,因为它很容易搞乱。例如,你可以想到在JS中更改基本数据类型的原型。例如:
Person.__proto__.arguments = "";
这非常非常糟糕。特别是如果你真的想这样做:
Person.prototype.arguments = "";
如果你不知道原型和__proto__之间的区别。 它们在不同的角度基本相同。
但是因为构造函数本身是函数的一个实例,所以如果直接在构造函数上调用__proto__,你将始终引用函数的构造函数。因此,在函数构造函数上更改某些内容会改变使用JS的所有函数,如果您更改了诸如参数之类的函数的整数,这可能会产生干扰。如果你深入了解它会变得非常讨厌......但你可以避免这些事情。
答案 3 :(得分:0)
我昨天刚刚学会了javascript对象的继承关系,并根据this good description制作了一个图表。希望它对你有用。