Javascript中的类型和语法(四) -- 强制类型转换相关函数

JavaScript中的强制类型转换总是返回标量基本类型值,如字符串、数字和布尔值,不会返回对象和函数。(强制类型转换则发生在动态类型语言的运行时(runtime)。)
“封装”,就是为标量基本类型值封装一个相应类型的对象,但这并非严格意义上的强制类型转换(类型转换发生在静态类型语言的编译阶段)。

1)ToPrimitive:

为了将对象 值转换为相应的基本类型值,抽象操作 ToPrimitive(参见 ES5 规范 9.1 节)会首先(通过内部操作 DefaultValue,参见 ES5 规范 8.12.8 节)检查该值是否有 valueOf() 方法。如果有并且返回基本类型值,就使用该值进行强制类型转换。如果没有就使用 toString()的返回值(如果存在)来进行强制类型转换。

如果 valueOf()toString() 均不返回基本类型值,会产生 TypeError 错误。
从 ES5开始,使用 Object.create(null) 创建的对象 [[Prototype]] 属性为 null,并且没有 valueOf() 和 toString() 方法,因此无法进行强制类型转换。因此是真的空对象。

ToPrimitive在Number(),==比较中会运用到。

var a = {
	valueOf: function(){
		return "42";
	},
	toString: function(){
		return "30";
	}
};
var b = {
	toString: function(){
		return "42";
	}
};
var c = [4,2];
c.toString = function(){
	return this.join( "" ); // "42"
};
Number( a ); // 42 先调用valueOf,不存在再调用toString
Number( b ); // 42
Number( c ); // 42
String(a);//"30" String转换对象会去调用toString
parseInt(a);//30 parseInt解析对象也会先调用toString

2)toString():

// 1.07 连续乘以七个 1000
var a = 1.07 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000;
// 七个1000一共21位数字
a.toString(); // "1.07e21"

//对普通对象来说,除非自行定义,否则 toString()(Object.prototype.toString())返回内部属性 [[Class]] 的值,如 "[object Object]"。

3)JSON 字符串化: JSON.stringify(…)

(3.1)对大多数简单值(字符串、数字、布尔值和 null )来说,JSON 字符串化和 toString() 的效果基本相同,只不过序列化的结果总是字符串:

JSON.stringify( 42 ); // "42"
JSON.stringify( "42" ); // ""42"" (含有双引号的字符串)
JSON.stringify( null ); // "null"
JSON.stringify( true ); // "true"

(3.2)JSON.stringify(…)对不安全的类型的处理:

//JSON.stringify(..) 在对象中遇到 undefined、function 和 symbol 时会自动将其忽略,
//在数组中则会返回 null(以保证单元位置不变)。
JSON.stringify( undefined ); // undefined
JSON.stringify( function(){} ); // undefined

JSON.stringify(
 [1,undefined,function(){},4]
); // "[1,null,null,4]" 在数组中遇到 undefined、function 和 symbol 时,会返回 null

JSON.stringify(
 { a:2, b:function(){} }
); // "{"a":2}" 在对象中遇到 undefined、function 和 symbol 时会自动将其忽略

(3.3)toJson(): 如果传递给 JSON.stringify(…) 的对象中定义了 toJSON() 方法,那么该方法会在字符串化前调用,以便将对象转换为安全的 JSON 值。(JSON.stringify(…)会对toJSON()的结果进行字符串化。) 因此,toJSON() 应该是“返回一个能够被字符串化的安全的 JSON 值”,而不是“返回一个 JSON 字符串”。

//对包含循环引用的对象执行 JSON.stringify(..) 会出错:
var o = { };
var a = { 
  b: 42,
  c: o,
  d: function(){}
};// 在a中创建一个循环引用
o.e = a;//循环引用

// 循环引用在这里会产生错误
// JSON.stringify( a );

// 自定义的JSON序列化
a.toJSON = function() {
  // 序列化仅包含b
  return { b: this.b };
};
JSON.stringify( a ); // "{"b":42}

/**toJSON不需要先做字符串化,可能会得到错误的结果**/
var a = {
 val: [1,2,3],
 // 可能是我们想要的结果!
 toJSON: function(){
 return this.val.slice( 1 );
 }
};
var b = {
 val: [1,2,3],
 // 可能不是我们想要的结果!
 toJSON: function(){
 return "[" +
 this.val.slice( 1 ).join() +
 "]"; 
 }
};
JSON.stringify( a ); // "[2,3]"
JSON.stringify( b ); // ""[2,3]""

(3.4)JSON.stringify(json, replacer,space):
<1>可选参数 replacer,它可以是数组或者函数,用来指定对象序列化过程中哪些属性应该被处理,哪些应该被排除,和 toJSON() 很像。
如果 replacer 是一个数组,那么它必须是一个字符串数组,其中包含序列化要处理的对象的属性名称,除此之外其他的属性则被忽略。
如果 replacer 是一个函数,它会对对象本身调用一次,然后对对象中的每个属性各调用一次,每次传递两个参数,键和值。如果要忽略某个键就返回 undefined,否则返回指定的值。
<2>可选参数space,用来指定输出的缩进格式。

/**replacer**/
var a = { 
 b: 42,
 c: "42",
 d: [1,2,3] 
};
JSON.stringify( a, ["b","c"] ); // "{"b":42,"c":"42"}" 只返回b,c属性
JSON.stringify( a, function(k,v){
 if (k !== "c") return v;
} );// "{"b":42,"d":[1,2,3]}"
/**space缩进自定义**/
var a = { 
 b: 42,
 c: "42",
 d: [1,2,3] 
};
JSON.stringify( a, null, 3 );
// "{
//    "b": 42,
//    "c": "42",
//    "d": [
//       1, 
//       2,
//       3
//    ]
// }"
JSON.stringify( a, null, "-----" );
// "{
// -----"b": 42,
// -----"c": "42",
// -----"d": [
// ----------1,
// ----------2,
// ----------3
// -----]
// }"

4)ToNumber():

true 转换为 1,false 转换为 0。undefined,转换失败的字符串 转换为 NaN,null 转换为 0。
对象(包括数组)会首先被转换为相应的基本类型值,如果返回的是非数字的基本类型
值,则再遵循以上规则将其强制转换为数字。

//Number中的进制转换
console.log(Number("0O10"));//8
console.log(Number("0X10"));//16
console.log(Number("010"));//10
console.log(010);//非严格模式8   严格模式报错
console.log(0O10);//8 
//Number中的特殊值转换
Number( "a" ); // NaN
Number( "" ); // 0
Number( [] ); // 0
Number( [ "abc" ] ); // NaN

5)ToBoolean

JavaScript 中的值可以分为以下两类:
(5.1) 可以被强制类型转换为 false 的值:
以下这些是假值:
undefined、 null、false、+0、-0 和 NaN、""
(5.2) 其他(被强制类型转换为 true 的值)
假值列表以外的都是真值

var a = new Boolean( false );
var b = new Number( 0 );
var c = new String( "" );
// "false" ,"0" ,"''" ,[] ,{} ,function(){} 也是真值

//a、b、c都是假值对象,但是它们皆为真值
var d = Boolean( a && b && c );//true
//为什么不用下面的方式判断三者的相与,因为js的&&与||实际是选择器运算符
//&&返回第一个假值,||返回第一个真值
var e = a && b && c;//String("") 前者都为真,返回最后一个的值

Boolean(…):

与 String(…) 和 Number(…) 一样,Boolean(…)(不带 new)是显式的 ToBoolean 强
制类型转换.

var a = "0";
var b = [];
var c = {};
var d = "";
var e = 0;
var f = null;
var g;
//Boolean转换 不加new
Boolean( a ); // true
Boolean( b ); // true
Boolean( c ); // true
Boolean( d ); // false
Boolean( e ); // false
Boolean( f ); // false
Boolean( g ); // false
new Boolean(g);//Boolean对象:__proto__: Boolean 
				//[[PrimitiveValue]]: false
//下面这种方式更常用
!!a; // true
!!b; // true
!!c; // true
!!d; // false
!!e; // false
!!f; // false
!!g; // false

//建议使用 Boolean(a) 和 !!a 来进行显式强制类型转换。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Funnee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值