当我有函数我想用作构造函数时,说:
function clog(x){
var text = x;
return console.log(text );
}
Run Code Online (Sandbox Code Playgroud)
我已经做了一些实例
var bla = new clog();
Run Code Online (Sandbox Code Playgroud)
现在我想添加新的功能,所以我会用
clog.prototype.alert = alert(text);
Run Code Online (Sandbox Code Playgroud)
如果我这样做会有什么不同:
clog.alert = alert(text);
Run Code Online (Sandbox Code Playgroud)
它不会被clog原型的对象继承吗?
T.J*_*der 45
由构造函数(clog在您的情况下)创建的实例继承对该clog.prototype对象的引用.因此,如果添加属性clog.prototype,它将显示在实例上.如果向clog自身添加属性,它将不会显示在实例上.
引用代码存在一些问题,让我们看一个抽象的例子:
function Foo() {
}
Foo.prototype.bar = "I'm bar on Foo.prototype";
Foo.bar = "I'm bar on Foo";
var f = new Foo();
console.log(f.bar); // "I'm bar on Foo.prototype"
// E.g., `f` inherits from `Foo.prototype`, not `Foo`
// And this link is live, so:
Foo.prototype.charlie = "I'm charlie on Foo.prototype";
console.log(f.charlie); // "I'm charlie on Foo.prototype";
Run Code Online (Sandbox Code Playgroud)
来自您的评论如下:
我不明白为什么
Foo原型链会忽略直接添加的新属性?
因为它Foo.prototype不是Foo,这是通过创建的对象的原型new Foo().
是不是
prototype简单地指向构造函数对象?
不,Foo并且Foo.prototype是完全不同的对象.Foo是一个函数对象,它像所有函数对象一样可以拥有属性.其中一个Foo属性是prototype,它是一个非功能对象,除了constructor指向的属性之外,它最初是空白的Foo.它Foo.prototype,不Foo,是参与JavScript的原型继承.new Foo唯一的作用是创建用作原型的对象(实际上,初始化对象; Foo操作符创建它们)Foo.prototype.
如果我
Foo为什么这样做new?
(为了避免混淆,我已经改变Foo到new上面,因为class是关键字.虽然你可以像你这样的ES5的使用它,最好不要.)
因为new几乎与之无关Foo.你可以找到它Foo,因为Foo它Foo.
一些ASCII艺术:
鉴于此代码:
function Foo() {
}
Foo.prototype.bar = "I'm bar on Foo.prototype";
Foo.bar = "I'm bar on Foo";
Run Code Online (Sandbox Code Playgroud)
我们有这些具有这些属性的对象(为清楚起见,省略了一些):
+???????????????????????????????????????+
| |
V +??????????????????+ |
+????????????????+ +??>| [String] | |
| Foo [Function] | | +??????????????????+ |
+????????????????+ | | "I'm bar on Foo" | |
| bar |????+ +??????????????????+ |
| prototype |????+ |
+????????????????+ | |
+??????????+ |
| |
V |
+?????????????+ |
| [Object] | |
+?????????????+ |
| constructor |??+ +????????????????????????????+
| bar |?????>| [String] |
+?????????????+ +????????????????????????????+
| "I'm bar on Foo.prototype" |
+????????????????????????????+
如果我们这样做
var f = new Foo();
Run Code Online (Sandbox Code Playgroud)
我们有(粗体新内容):
+??????????????????????????????????????????+
| |
V +??????????????????+ |
+????????????????+ +??>| [String] | |
| Foo [Function] | | +??????????????????+ |
+????????????????+ | | "I'm bar on Foo" | |
| bar |????+ +??????????????????+ |
| prototype |????+ |
+????????????????+ | |
+?????????????+ |
| |
V |
+???????????????+ +?????????????+ |
| f [Object] | +?????>| [Object] | |
+???????????????+ | +?????????????+ |
| [[Prototype]] |??????????+ | constructor |??+ +????????????????????????????+
+???????????????+ | bar |????>| [String] |
+?????????????+ +????????????????????????????+
| "I'm bar on Foo.prototype" |
+????????????????????????????+
Foo.newProp = "new addition" 并不是字面上的属性名称(至少在大多数引擎上都没有),但它是对象与其原型对象的内部链接.
现在假设我们这样做:
f.charlie = "I'm charlie on f";
Run Code Online (Sandbox Code Playgroud)
所有改变都是f.newProp => undefined对象(粗体的新东西):
+??????????????????????????????????????????+
| |
V +??????????????????+ |
+????????????????+ +??>| [String] | |
| Foo [Function] | | +??????????????????+ |
+????????????????+ | | "I'm bar on Foo" | |
| bar |????+ +??????????????????+ |
| prototype |????+ |
+????????????????+ | |
+?????????????+ |
| |
V |
+???????????????+ +?????????????+ |
| f [Object] | +?????>| [Object] | |
+???????????????+ | +?????????????+ |
| [[Prototype]] |??????????+ | constructor |??+ +????????????????????????????+
| charlie |??????????+ | bar |?????>| [String] |
+???????????????+ | +?????????????+ +????????????????????????????+
| | "I'm bar on Foo.prototype" |
| +????????????????????????????+
|
| +????????????????????+
+?????>| [String] |
+????????????????????+
| "I'm charlie on f" |
+????????????????????+
Foo.new = ...现在有自己的财产,叫做Foo.newProp = ....这意味着这两个陈述:
console.log(f.charlie); // "I'm charlie on f"
console.log(f.bar); // "I'm bar on Foo.prototype"
Run Code Online (Sandbox Code Playgroud)
处理略有不同.
我们new先来看看吧.这是引擎的用途Foo.newProp:
f没有自己的属性叫f.constructor.newProp?很简单.现在让我们看一下引擎的处理方式f.constructor:
Foo没有自己的属性叫Object.getPrototypeOf?__proto__有原型?__proto__原型有一个名为f?的属性?所以f和之间有一个很大的区别charlie:f.charlie有自己的属性调用f.charlie,但是一个被称为的继承属性f.如果"charlie"原型对象没有调用属性f.bar,那么它的原型对象(在这种情况下f)将被检查,依此类推,直到我们用完原型.
您可以使用"bar"所有对象具有的函数来测试属性是否为"自己的"属性(btw):
console.log(f.hasOwnProperty("charlie")); // true
console.log(f.hasOwnProperty("bar")); // false
Run Code Online (Sandbox Code Playgroud)
从评论中回答你的问题:
我制作
f然后f如何解决内在"bar"属性?
在对表达式f.charlie的一部分的调用中f.bar,f引用将由charlie表达式返回的新生成的对象.所以,当你这样做时bar,你将一个属性直接放在该对象上,与原型无关.
换句话说,这两个例子产生完全相同的f对象:
// Example 1:
function Person(name) {
this.name = name;
}
var p = new Person("Fred");
// Example 2:
function Person() {
}
var p = new Person();
p.name = "Fred";
Run Code Online (Sandbox Code Playgroud)
以下是我提到的引用代码的问题:
问题1:从构造函数返回一些东西:
function clog(x){
var text = x;
return console.log(text ); // <=== here
}
Run Code Online (Sandbox Code Playgroud)
在99.9999%的时间内,您不希望从构造函数中返回任何内容.该bar操作的工作方式是:
Object.prototype属性中分配了一个原型.hasOwnProperty引用新对象.function Person(first_name, last_name) {this.first_name = first_name; this.last_name = last_name;}表达式的结果是在步骤1中创建的对象.var ilya = new Person('ilya', 'D')操作的结果是该对象.因此,在您的情况下,由于name不返回任何内容,您只需Person从代码中删除关键字即可.但是如果你使用new Person(...)带有返回对象的函数的那个构造,你就会弄乱你的构造函数.
问题2:调用函数而不是引用函数
在这段代码中:
clog.prototype.alert = alert(text);
Run Code Online (Sandbox Code Playgroud)
你正在调用该this函数并将其结果分配给一个名为newon 的属性this.prop = "value";.因为p不返回任何东西,它完全等同于:
alert(text);
clog.prototype.alert = undefined;
Run Code Online (Sandbox Code Playgroud)
......这可能不是你的意思.也许:
clog.prototype.alert = function(text) {
alert(text);
};
Run Code Online (Sandbox Code Playgroud)
在那里,我们创建一个函数并将其引用分配给new原型上的属性.调用该函数时,它将调用该标准prototype.
问题3:构造函数应该初始上限
这只是样式,但它是绝对标准的:构造函数(与之一起使用的函数this)应该以大写字母开头,new而不是new.不过,这只是风格.
| 归档时间: |
|
| 查看次数: |
10310 次 |
| 最近记录: |