JavaScript&;原型上的默认值

JavaScript&;原型上的默认值,javascript,Javascript,我对JavaScript非常陌生。我已经在谷歌搜索了很多次,但是没有找到我想要的答案——可能是因为我使用了错误的术语 前几天,我正在阅读一篇关于创建JavaScript组件的基本教程: 本教程的一部分涉及一组默认选项,这些选项指定给类型的原型链: SimpleAlert.prototype.options = { wrapper : document.body, type : "default", message : "Default message." } 其思想是,如果用户在构

我对JavaScript非常陌生。我已经在谷歌搜索了很多次,但是没有找到我想要的答案——可能是因为我使用了错误的术语

前几天,我正在阅读一篇关于创建JavaScript组件的基本教程:

本教程的一部分涉及一组默认选项,这些选项指定给类型的原型链:

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
是一个局部变量函数变量,而不是实例变量。这很有意义。感谢您的精彩解释和示例。