超能刚哥

浅谈toString/toLocaleString

发表于2016-02-22

1. toString()

这个方法相信大家都用过,JS里面的每个对象都有这个方法,其作用是返回对象的字符串表示形式

1.1 object.toString()

默认情况下,object.toString()会返回[object type],其中type即为object的类型:

var a = {};
console.log(a.toString()); //[object Object]

然而当你试图调用array.toString()时候得到的并不是[object Array],那是因为除了Object之外的其他对象都对自身的toString()方法进行了重写以便得到合适的返回值,所以正确的调用姿势应该是这样:

var objectToString = function(_object) {
    return Object.prototype.toString.call(_object);
}
console.log(objectToString([])); // [object Array]
console.log(objectToString(true)); // [object Boolean]
console.log(objectToString({})); // [object Object]
console.log(objectToString(11)); // [object Number]
console.log(objectToString('Hi')); // [object String]
console.log(objectToString(new Date())); // [object Date]
console.log(objectToString(function(){})); // [object Function]
console.log(objectToString(null)); // [object Null]
console.log(objectToString()); // [object Undefined]

在浏览器环境里面,直接执行toString(),会输出[object Window],因为所有的全局方法都是挂在window这个对象上面的

1.2 array.toString()

按上文说的,虽然Array也是一个对象,但是Array.prototype.toString已经不是从Object上继承下来的那个方法了

[1,2,3].toString(); // '1,2,3'
[1,{},true,new Date(),[]].toString(); // "1,[object Object],true,Mon Feb 22 2016 20:53:47 GMT+0800 (CST),"

所以array.toString()会对数组的每个元素执行一次对应的toString()方法并用”,”join出一段字符串返回
思考下面的示例:

console.log([1,[2,[3,4]],5,[6,7,[8,[9,[10,11]]]]].toString());

1.3 number.toString(radix)

在数字对象上调用toString()方法,会返回这个数字的字符串形式。
另可指定一个参数作为数字到字符串的转换的基数(从2到36)。如果未指定 radix 参数,则默认值为 10

console.log(new Number(1).toString()); // '1'
console.log(123..toString()); // '123'
console.log(123.1.toString()); // '123.1'
console.log(15..toString(16)); // 'f'
console.log(0xf.toString(10)); // '15'

在整形数字字面量上调用toString()方法时要注意需要两个点号(.),具体原因可以自己琢磨:)。

1.4 function.toString()

通常来说,对一个函数执行toString(),会原封不动地返回这个函数的定义代码,包括不必要的空格和换行:

function foo() {
var a =     1;
      return a;
}
console.log(foo.toString());
// "function foo() {
// var a =     1;
//       return a;
// }"

当然也有些例外,比如对JS原生函数/方法调用toString():

parseInt.toString(); //"function parseInt() { [native code] }"

以前见过某大神通过特别的方法来“泄露出”原生函数的定义代码,可惜没把招数记下来。

PS:在一些旧版本的火狐里面,对这个方法是通过反编译字节码来实现的,不仅返回的代码和定义的可能不一致,而且定义函数时如果父作用域开启了’use strict’,那对该函数调用toString()也会看到多出了’use strict’这段字符串

1.5 boolean.toString()

true.toString(); // 'true'
false.toString(); // 'false'

1.6 error.toString()

var e = new Error("fatal error");
console.log(e.toString()); // "Error: fatal error"
e.name = undefined;
console.log(e.toString()); // "Error: fatal error"
e.name = "";
console.log(e.toString()); // "fatal error"
e.message = undefined;
console.log(e.toString()); // "Error"
e.name = "hello";
console.log(e.toString()); // "hello"

1.7 date.toString()

console.log(new Date().toString()); // "Mon Feb 22 2016 21:57:19 GMT+0800 (CST)"

1.8 regexp.toString()

new RegExp(/\d/).toString(); // '/\d/'
/\D/.toString(); // '/\D/'

另外还有symbol().toString(),不过暂时还没了解Symbol对象到底是干啥的,所以日后再说吧


2. toLocaleString()

每个对象也都有自己的toLocaleString()方法,其字面意义是返回这个对象在特定语言环境下的字符串内容,而且并不是所有的对象都重写了这个方法。
通常情况下,一个对象的toLocaleString()方法的返回值与其toString()方法的返回值是一致的,但是下面这几种对象重写了它们的toLocaleString()方法:

2.1 number.toLocaleString([locales [, options]])

我们知道数字这种东西在不同环境下的表示方法都不一样,通过调用一个数字对象(或者数字字面量)的toLocaleString()方法并指定特定的地区参数,我们可以很方便的得到更适合的值。

最简单的数字按千分位分割:

var a = 123456789;
console.log(a.toLocaleString()); // "123,456,789"

来看看MDN上的更多示例:

var number = 123456.789;

// 在德国点(.)号是作为千分位符号而逗号(,)则作为小数点。Orz
alert(number.toLocaleString("de-DE"));
// → 123.456,789

// 这才是真正的阿拉伯数字
alert(number.toLocaleString("ar-EG"));
// → ١٢٣٤٥٦٫٧٨٩

// 看看三哥的奇葩数字表示法
alert(number.toLocaleString("en-IN"));
// → 1,23,456.789

// 大汉子勃大茎深
alert(number.toLocaleString("zh-Hans-CN-u-nu-hanidec"));
// → 一二三,四五六.七八九

// 当一个语言关键字可能不被支持的时候,还可以指定一个备用的关键字,比如下面情况:
alert(number.toLocaleString(["ban", "id"]));
// → 123.456,789

该方法第二个参数是一个可选的对象,请看示例:

var number = 123456.789;

// request a currency format
alert(number.toLocaleString("de-DE", {style: "currency", currency: "EUR"}));
// → 123.456,79 €

// the Japanese yen doesn't use a minor unit
alert(number.toLocaleString("ja-JP", {style: "currency", currency: "JPY"}))
// → ¥123,457

// limit to three significant digits
alert(number.toLocaleString("en-IN", {maximumSignificantDigits: 3}));
// → 1,23,000

更详细的内容请参见: Number.prototype.toLocaleString()

2.2 date.toLocaleString()

日期对象的toLocaleString()方法与数字对象的toLocaleString()方法很类似,并且通常比date.toString()更加有用:

console.log(new Date().toLocaleString()); // "2016/2/23 下午12:38:29"

请看MDN上的示例:

var date = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));

// formats below assume the local time zone of the locale;
// America/Los_Angeles for the US

// US English uses month-day-year order and 12-hour time with AM/PM
console.log(date.toLocaleString('en-US'));
// → "12/19/2012, 7:00:00 PM"

// British English uses day-month-year order and 24-hour time without AM/PM
console.log(date.toLocaleString('en-GB'));
// → "20/12/2012 03:00:00"

// Korean uses year-month-day order and 12-hour time with AM/PM
console.log(date.toLocaleString('ko-KR'));
// → "2012. 12. 20. 오후 12:00:00"

// Arabic in most Arabic speaking countries uses real Arabic digits
console.log(date.toLocaleString('ar-EG'));
// → "٢٠‏/١٢‏/٢٠١٢ ٥:٠٠:٠٠ ص"

// for Japanese, applications may want to use the Japanese calendar,
// where 2012 was the year 24 of the Heisei era
console.log(date.toLocaleString('ja-JP-u-ca-japanese'));
// → "24/12/20 12:00:00"

// when requesting a language that may not be supported, such as
// Balinese, include a fallback language, in this case Indonesian
console.log(date.toLocaleString(['ban', 'id']));
// → "20/12/2012 11.00.00"

更详细的内容请参见: Date.prototype.toLocaleString()

2.3 array.toLocaleString()

对一个数组对象调用toLocaleString(),实际上是对数组的每个元素分别调用了对应的toLocaleString(),并将各个结果用本地化分隔符(通常是”,”)join出一段字符串然后返回

var a = [1,2,3];
console.log(a.toLocaleString()); // "1,2,3" 与toString()的返回值一致
var b = [11111,new Date(),{}];
console.log(b.toLocaleString()); // "11111,2016/2/23 下午12:31:09,[object Object]"

请注意上面例子中的数组b的第一个元素并没有被千分位分割哦。

3 补充

3.1 string.toUpperCase()和string.toLowerCase()

很明显,用于对字符串进行大小写转换

console.log('abc'.toUpperCase()); // "ABC"
console.log('ABC'.toLowerCase()); // "abc"

3.2 string.toLocaleUpperCase()和string.toLocaleLowerCase()

大多数情况下这俩货的返回值和上面俩货的返回值是一样的,MDN也只提到在个别环境(比如土耳其语)下会返回不同的值。


暂时先说到这儿吧,文中的一些坑有时间再填。

该文章暂无评论,赶快抢占沙发!

发表评论

电子邮件地址不会被公开。 必填项已用*标注