0

我是 JavaScript 新手,在使用默认值定义基本对象的属性和方法时,我试图了解对象构造函数与原型。

// base object
function Animal (nameArg, typeArg) {
    this.name = nameArg,
    this.type= typeArg,
    this.sayHello = function() {
        console.log("Hello my name is", this.name, " and I am an ", this.type);
    }
}
// Setting defaults
Animal.prototype.name = "Anonymous";
Animal.prototype.type = "Animal";

//instantiating an animal WITHOUT any arguments passed in
var cat = new Animal; // I am getting undefined when I try to access properties like name

//instantiating an animal WITH argguments passed in
var lion = new Animal("Jimmy", "Lion"); // works as expected
4

7 回答 7

2

如果您要实例化函数,则无需使用原型。另外,我会在之后添加括号来调用构造函数:Animal

// base object
function Animal (nameArg, typeArg) {
    this.name = nameArg || "Anonymous";
    this.type= typeArg || "Animal";
    this.sayHello = function() {
        console.log("Hello my name is", this.name, " and I am an ", this.type);
    };
}

//instantiating an animal WITHOUT any arguments passed in
var cat = new Animal(); // <-- note the brackets

//instantiating an animal WITH argguments passed in
var lion = new Animal("Jimmy", "Lion");

您的代码版本不起作用的原因是,尽管您没有传递任何参数,但构造方法Animal将原始变量设置为undefined,覆盖原型默认值。

于 2013-09-20T09:41:54.127 回答
1
function Animal (args) {
    if(typeof args === 'object') {
        this.name = 'nameArg' in args ? args.nameArg : default_value,
        this.type = 'typeArg' in args ? args.typeArg : default_value,
    }
    else
    {
        this.name = default_value;
        this.name = default_value;
    }
}

new Animal({});
new Animal({nameArg: 'hehe'});
new Animal({typeArg: 'hehe'});
new Animal({nameArg: 'hehe', typeArg: 'hehe'});
于 2013-09-20T09:41:45.763 回答
1

你做错了什么

您将其设置为undefined:它本身就是一个值。你根本不应该定义它来让它工作:

// base object
function Animal (nameArg, typeArg) {
    if (nameArg) this.name = nameArg;
    if (typeArg) this.type = typeArg;
    // could be added to prototype, it's the same for each instance
    this.sayHello = function () { console.log("Hello my name is " + this.name + " and I am an " + this.type); }; // don't use commas here, use the + operator instead
}

// Setting defaults
Animal.prototype.name = "Anonymous";
Animal.prototype.type = "Animal";

var cat = new Animal(); // passing no arguments to constructor
cat.sayHello(); // now gives correct result ("Hello my name is Anonymous and I am an Animal")

//instantiating an animal WITH argguments passed in
var lion = new Animal("Jimmy", "Lion"); // always worked

为什么会这样

实际上,设置为未定义的变量和从未定义的变量之间存在差异,这很有趣——这又是 JavaScript 的另一个常见怪癖。要区分未定义变量和未定义变量,请看以下示例:

var foo = { x: undefined };
console.log('x' in foo); // true, x has been defined as "undefined"
console.log('y' in foo); // false, foo.y has never been defined

JavaScript 中的参数默认为undefined,类似于最初定义变量时没有为其设置值或显式设置为undefined

function test(arg)
{   console.log(arg); // undefined
    console.log(doesNotExist); // ReferenceError: doesNotExist is not defined
}
test(); // run and see

通过分配给它,JavaScript 会记录它被分配的内容,因此不会查找原型链来查看属性是否存在(参考)。

于 2013-09-20T09:41:50.603 回答
1

将您的构造函数更改为:

function Animal (nameArg, typeArg) {
    this.name = nameArg || this.name; // if nameArg is not defined take default instead
    this.type= typeArg || this.type; // if typeArg is not defined take default instead
    this.sayHello = function() {
        console.log("Hello my name is", this.name, " and I am an ", this.type);
    }
}

进而:

var cat = new Animal();
于 2013-09-20T09:42:44.767 回答
0

您以正确的方式设置默认值,但在构造函数中覆盖它们。试试这个:

function Animal (nameArg, typeArg) {
    if (nameArg != null) this.name = nameArg,
    if (typeArg != null) this.type = typeArg,
    this.sayHello = function() {
        console.log("Hello my name is", this.name, " and I am an ", this.type);
    }
}

此外,在原型上设置 sayHello 方法是一个巨大的胜利,不仅仅是使用原型作为默认值。

于 2013-09-20T09:42:05.953 回答
0

cat = new Animal()基本上是cat = new Animal( undefined, undefined ),这些参数被用作this.namethis.type。要不覆盖原型中的默认值,只需检查是否提供了参数:

function Animal (nameArg, typeArg) {
    if(nameArg) this.name = nameArg;
    if(typeArg) this.type= typeArg;
    this.sayHello = function() {
        console.log("Hello my name is", this.name, " and I am an ", this.type);
    }
}

http://jsfiddle.net/K6Wu8/

于 2013-09-20T09:42:54.630 回答
0

如果传入了 undefined,您可以使用||将默认值设置为原型值。

function Animal (nameArg, typeArg) {
    this.name = nameArg || this.name,
    this.type= typeArg || this.type,
    this.sayHello = function() {
        console.log("Hello my name is", this.name, " and I am an ", this.type);
    }
}
// Setting defaults
Animal.prototype.name = "Anonymous";
Animal.prototype.type = "Animal";

//instantiating an animal WITHOUT any arguments passed in
var cat = new Animal; // I am getting undefined when I try to access properties like name

//instantiating an animal WITH argguments passed in
var lion = new Animal("Jimmy", "Lion"); // works as expected

小提琴示例 - http://jsfiddle.net/LwsRE/

于 2013-09-20T09:43:16.347 回答