JavaScript&;原型上的默认值
我对JavaScript非常陌生。我已经在谷歌搜索了很多次,但是没有找到我想要的答案——可能是因为我使用了错误的术语 前几天,我正在阅读一篇关于创建JavaScript组件的基本教程: 本教程的一部分涉及一组默认选项,这些选项指定给类型的原型链:JavaScript&;原型上的默认值,javascript,Javascript,我对JavaScript非常陌生。我已经在谷歌搜索了很多次,但是没有找到我想要的答案——可能是因为我使用了错误的术语 前几天,我正在阅读一篇关于创建JavaScript组件的基本教程: 本教程的一部分涉及一组默认选项,这些选项指定给类型的原型链: SimpleAlert.prototype.options = { wrapper : document.body, type : "default", message : "Default message." } 其思想是,如果用户在构
SimpleAlert.prototype.options = {
wrapper : document.body,
type : "default",
message : "Default message."
}
其思想是,如果用户在构造过程中提供不同的参数,则可以使用不同的参数创建simplelert
类型,否则将使用默认选项
simplelert
构造函数如下所示:
function SimpleAlert( options ) {
this.options = extend( {}, this.options ); // Why?
extend( this.options, options );
// start the functionality...
}
extend
功能定义为:
function extend( a, b ) {
for( var key in b ) {
if( b.hasOwnProperty( key ) ) {
a[key] = b[key];
}
}
return a;
}
我对本规范的理解是:
创建新的simplelert
对象需要用户传入自己的选项
对象。假设我通过了选项
参数的{test:“Testing”}
。extend
函数然后访问this.options
(我认为这是指原型的options
实例,因为在范围中没有定义其他options
变量),基本上将所有内容从共享实例复制到空的{}
对象,然后将其分配给共享的this.options
实例
然后,用户提供的选项
(在我的例子中,{test:“Testing”}
是扩展
到这个.options
共享实例中(基本上是将额外的测试
字段复制到共享实例中)
但实际上,在本例中,共享实例似乎没有受到影响——这意味着simplelert.prototype.options
声明保持不变,以便simplelert
的每个新实例都可以访问它(这就是我想要的)
然而,在我的实验中,我发现更改this.options
会导致原型值被修改……我确信无论我做错什么都很容易修复,但我看不到。以下是一个示例:
var Animal = function(ovr) {
if (arguments.length > 0)
{
this.options.mode = ovr;
}
};
Animal.prototype.options = { mode: "Test" }; / I want this to be default for all instances created
var test = new Animal("Override"); // set this test obj to use "Overide"
console.log(test.options.mode); // outputs Override as expected
var again = new Animal();
console.log(again.options.mode); // also outputs Override (I want it to say "Test")
感谢您的帮助!正如您在代码中所建议的,它缺少“复制”操作,因此您正在修改原型上的共享对象
var Animal = function(ovr) {
if (arguments.length > 0) {
// Copy whatever is on this.options to a blank object,
// then assign this.options to be that newly copied object, so
// the prototype object is masked by the instance object.
this.options = Object.assign({}, this.options);
this.options.mode = ovr;
}
};
这可能有助于理解实例属性如何“屏蔽”原型:
var Foo = function() {
console.log('a', this.x);
this.x = 100;
console.log('b', this.x);
delete this.x;
console.log('c', this.x);
};
Foo.prototype.x = 1;
new Foo();
正如您在代码中所建议的,它缺少“复制”操作,因此您正在修改原型上的共享对象
var Animal = function(ovr) {
if (arguments.length > 0) {
// Copy whatever is on this.options to a blank object,
// then assign this.options to be that newly copied object, so
// the prototype object is masked by the instance object.
this.options = Object.assign({}, this.options);
this.options.mode = ovr;
}
};
这可能有助于理解实例属性如何“屏蔽”原型:
var Foo = function() {
console.log('a', this.x);
this.x = 100;
console.log('b', this.x);
delete this.x;
console.log('c', this.x);
};
Foo.prototype.x = 1;
new Foo();
谢谢你的回答。我仍然不理解一些东西。this.options是原型上的共享实例,对吗?So Object.assign({},this.options}将共享实例复制到一个空对象…然后该对象(现在已填充)被重新分配回此.options…哪个是共享实例,对吗?不,不是。简单来说,当您请求“this.options”时,它会首先在实例上查找options属性。如果不存在,则会查找原型链。因此,实例选项“masks”prototype.Updated answer.噢,好吧,那么
Foo
构造函数中this.x
的赋值是隐式创建了一个隐藏在原型变量后面的变量?奇怪的是,我注意到如果我将this.x=100;
更改为var x=100
,它似乎不会隐藏?因为var
是一个局部变量函数变量,而不是实例变量。这很有意义。谢谢你的精彩解释和示例。谢谢你的回答。我仍然不理解一些东西。this.options是原型上的共享实例,对吗?So Object.assign({},this.options}将共享实例复制到一个空对象…然后那个对象(现在已填充)被重新分配回此.options…哪个是共享实例,对吗?不,不是。简单地说,当您请求“this.options”时,它会首先在实例上查找options属性。如果不存在,则会查找原型链。因此,实例选项“masks”prototype.Updated answer.噢,好吧,那么Foo
构造函数中this.x
的赋值是隐式创建了一个隐藏在原型变量后面的变量?奇怪的是,我注意到如果我将this.x=100;
更改为var x=100
,它似乎不会隐藏?因为var
是一个局部变量函数变量,而不是实例变量。这很有意义。感谢您的精彩解释和示例。