16

我对 JavaScript 有点陌生,我有一个问题。

我知道你可以设置变量和“子变量”。喜欢:

var msg = "Hello World";
alert(msg);

并且

var msg = {
    lipsum: "Lorem Ipsum Dolor Sit Amet"
}
alert(msg.lipsum);

但我想知道你是否可以两者都做,比如

var msg = "Hello World" || {
    lipsum: "Lorem Ipsum"
}
alert(msg + msg.lipsum);

这样,您可以声明一个变量,并将相同的变量作为一个对象。显然它不能用我所做的来完成,但你明白了。

任何帮助将非常感激!

4

6 回答 6

20

事实上,你可以。

var msg = {
    lipsum: "Lorem Ipsum",
    toString: function() {return "Hello World!"}
};
于 2013-01-15T02:07:54.107 回答
12

JavaScript 变量可以包含对象或原语。如果你有一个对象,你可以在它上面设置属性(子变量),如果你有一个原语,你不能。

回到您的示例,JavaScript 字符串可以是基元也可以是对象,具体取决于您如何定义它,并且为了使事情更加混乱,当您尝试访问其属性时,基元将临时转换为对象。

以下代码将显示“bar”,因为我们的字符串被明确声明为带有new关键字的 String 对象:

a = new String("Hello World");
a.foo = "bar";
alert(a.foo);

如果我们删除该new String部分,我们会得到一个原语。当我们尝试设置时,JavaScript 会为我们转换它foo,但没有保存任何内容,因为它实际上只是下面的一个原语,当我们调用时我们会返回结果“未定义” alert(b.foo)

b = "Hello World";
b.foo = "bar";
alert(b.foo);

这只是内置 JavaScript 类型令人困惑的许多事情之一,我建议阅读Mozilla Javascript Reference 的 Global Objects 部分以了解所有血腥细节。

于 2013-01-15T02:24:44.527 回答
6

Kolink 是绝对正确的,只要您希望该值是一个字符串,那么您就可以将值“装箱”在一个对象中,然后覆盖toString方法。但是,所做的只是允许 javascript(当它需要将对象输出为字符串时)输出变量(通过本机调用toString您)。它不是返回原始值,而是一个装在另一个对象中的值。

我想指出几件事情,让人们知道这两者是如何变化的(举几个例子)。所以,让我们看下面的部分:

var BoxedString = {
  value: 'Hello, world!',
  toString: function(){ return this.value; }
};
var BoxedNumber = {
  value: 3.14,
  toString: function(){ return this.value; }
};
var BoxedDate = {
  value: new Date(), // today
  toString: function(){ return this.value; }
};

很简单,我们可以在必要时将这些中的每一个输出为字符串(或者我们可以吗?)

// Each of these implicitly calls `.toString()` because we're concatenating
// them within another string. Metho calls (like `alert()` that look for a 
// string result have the same effect.
console.log('BoxedString: '+BoxedString); // BoxedString: Hello, world!
console.log('BoxedNumber: '+BoxedNumber); // BoxedNumber: 3.14
console.log('BoxedDate:   '+BoxedDate);   // fail!

等等,BoxedDate失败;这是为什么?因为我们toString正在返回Date对象并且不能按原样输出。但是,如果我们将其更改BoxedDate.toString为 return this.value.toString(),我们会看到更好的结果(继续尝试,我会等待。)

让我们BoxedDate顺应潮流,试试日期法:

console.log(BoxedDate.getFullYear()); // BoxedDate.getFullYear is not a function

再一次,它实际上不是一个Date,它是一个Date包裹在一个闪亮的盒子里。奇怪的是,Javascript 足够了解隐式转换BoxedNumber

var sum = 38.86 + BoxedNumber; // 42 (works)

但是,不要尝试任何Number对象方法,例如toFixed(). 与BoxedString和 字符串方法相同,例如.replace(),toUpperCase()和其他。

但是,如果我要在@Kolink 的答案中添加一些内容,那也将包括valueOf作为对象声明的一部分。就像是:

var BoxedValue = {
  value: 2013,
  toString: function(){ return this.value.toString(); }
  valueOf: function(){ return this.value; }
};
于 2013-01-15T03:11:52.050 回答
2

您可以通过创建一个新对象并扩展原型toString()方法来做到这一点。像这样的东西应该工作:

function Msg() {
    this.message = 'some message';
    this.lipsum = 'lipsum';
}

Msg.prototype.toString = function() {
    return this.message;
}

var msg = new Msg();

alert(msg + msg.lipsum);
于 2013-01-15T02:09:43.187 回答
1

实际上"Hello World"是一个字符串文字typeof "Hello World" === "string"),而不是任何东西的实例。

你可以创建一个

var s = new String("Hello World");

这就是现在typeof s === "object"和。instanceof StringObject

字符串对象还可以具有其他属性,例如

s.hint = "!";
// console.log(s + s.hint) prints "Hello World!" into console

你真正需要的很可能是其他人回答的;)

于 2013-01-15T02:17:13.237 回答
1

只要您的变量不是原始变量,您就可以为其添加属性。

在你的情况下

var msg = "Hello World";

msg是一个原始变量,所以你无法实现你想要的。但是您可以创建一个真实的String object并添加它的属性。

var msg = new String("Hello World");
msg.lipsum = "lipsum";
alert(msg + msg.lipsum);
于 2013-01-15T02:18:10.980 回答