您的位置:首页 > Web前端 > JavaScript

JavaScript学习(四):JavaScript类型转换以及变量作用域

2015-11-10 15:33 766 查看
3.8 类型转换
JavaScript中的取值类型非常灵活,从布尔值可以看到这一点:当JavaScript期望使用一个布尔值的时候,可以提供任何值,JavaScript将根据需要自行转换类型,真值转换成true,假值转换成false



3.8.1 转换和相等性
因为JavaScript可以做灵活的类型转换,因此“=="相等运算符也随相等的含义灵活多变。
null == undefined //true
"0" == 0 //true
0 == false //true
"0" == false //true
*需要注意的是,一个值转换成另一个值并不意味着两个值相等,比如,在期望使用布尔值的地方使用了undefined,undefined会转换成false,但并不表明undefined == false.
3.8.2 显式类型转换
尽管JavaScript可以自动做许多类型转换,但有时仍需要做显式转换,或者为了使代码变得清晰易读而做显式转换。
做显式类型转换最简单的方法就是使用Boolean()、Number()、String()或Object()函数。(除了null和undefined之外任何值都具有toString()方法,这个方法执行结果通常和String()方法返回的结果是一样的)

JavaScript中提供了专门的函数和方法用来做更精确的数字到字符串(number-to-string)和字符串到数字(string-to-number)的转换。
Number类定义的toString()方法可以接收表示转换基数的可选参数(二、八、十等进制数),如果不指定此参数,转换规则将是基于十进制。
var n = 17;
binary_string = n.toString(2); //"10001"
octal_string = "0" + n.toString(8); // "021"
hex_string = "0x" + n.toString(16); //"0x11"
控制输出中小数点位置和有效数字位数,或者决定是否需要指数计数法。
toFixed()---根据小数点后的指定位数将数字转换成字符串,不使用指数记数法。
toExponential()----使用指数记数法将数字转换成指数形式的字符串,其中小数点前只有一位,小数点后的位数则由参数决定(有效数字位数比指定位数多一位)。
toPrecision()----根据指定的有效数字位数将数字转换成字符串,如果有效数字的位数少于数字整数部分的 位数,则转换成指数形式。
var n = 123456.789;
n.toFixed(0); // "123457"
n.toFixed(2); //"123456.79"
n.toFixed(5); // "123456.78900"
n.toExponential(1); //"1.2e+5"
n.toExponential(3); //"1.235e+5"
n.toPrecision(4); //"1.235e+5"
n.toPrecision(7); //"123456.8"
n.toPrecision(10); //"123456.7890"
通过Number()转换函数传入一个字符串,它会试图将其转换成一个整数或浮点数直接量,这个方法只能基于十进制数进行转换,并且不能出现非法的为尾随字符。
parseInt()和parseFloat()(全局函数,不从属于任何类的方法).parseInt()值解析整数,而parseFloat()则可以解析整数和浮点数,如果字符串前缀是“0x”或者“0X”,parseInt()将其解释为十六进制数,parseInt和parseFloat都会跳过任意数量的前导空格,尽可能解析更多数值字符,并忽略后面的内容。如果第一个非空格字符是非法的数字直接量,将最终返回NaN;
parseInt可以接收第二个可选参数,这个参数指定数字转换的基数,合法的取值范围是2-36.

parseInt("3 blind mice "); // 3
parseFloat(" 3.14 meter"); //3.14
parseInt(" -12.34"); //-12
parseInt("0xFF"); // 255
parseInt("0.1"); //0
parseInt("11",2); // 3
parseInt("ff",16); //255
parseInt(".1"); //NaN:整数不能以.开头

parseFloat(".1"); //0.1
parseFloat("$72.74"); //数字不能以$开头

3.8.3 对象转换成原始值

对象到布尔值:所有对象均转换成true,包装对象也是如此,new Boolean(false)是一个对象而不是原始值,将转换成true。
*本地对象、内置对象、宿主对象:http://www.w3school.com.cn/js/pro_js_object_types.asp
宿主对象根据各自的算法可以转换成字符串和数字,此下的规则只适用于本地对象。

所有对象都继承了两个方法。

toString()----返回一个反映这个对象的字符串

很多类定义了更多版本的toString()方法。
数组(Array class)的toString()方法将每个数组元素转换成一个字符串,并在元素之间添加逗号后合并成结果字符串。
函数类(Function class)的toString()方法返回这个函数的实现定义的表示方式,实际上就是把函数转换成JavaScript源代码字符串。
日期类定义的toString()方法返回一个可读的日期和时间字符串
RegExp()定义的toString()方法将RegExp对象转换为表示正则表达式直接量的字符串:
({x:1 , y:2}).toString() //"[object Object]"
[1,2,3].toString() //"1,2,3"
var fx = function (x){return x;};
fx.toString() //"function (x){return x;}"
new Date().toString() //"Mon Nov 09 2015 07:57:44 GMT+0800"
new RegExp(/\d+/g).toString() //"/\d+/g"

2. valueOf()---存在任意原始值,默认将对象转换成它的原始值;对象是复合值,而且大多数对象无法真正表示为一个原始值,因此默认的valueOf()方法简单的返回对象本身,而不是返回一个原始值。
数组、函数、正则表达式简单的继承了此方法,调用这些类型的实例的valueOf()方法只是简单的返回对象本身。日期类定义的valueOf()方法会返回它的一个内部表示:1970年一月一日以来的毫秒数。
({x:1 , y:2}).valueOf() //Object { x=1, y=2}
[1,2,3].toString() //[1,2,3]
var fx = function (x){return x;};
fx.toString() //"function (x)"
new Date().valueOf() //1447028184881
new RegExp(/\d+/g).valueOf() //RegExp /\d+/g

JavaScript对象到字符串的转换:

如果对象具有toString()方法,则调用此方法。如果它返回一个原始值,JavaScript将这个原始值转换成字符串(如果本身不是字符串的话),并返回字符串结果。
如果没有toString()方法,或者这个方法不返回一个原始值,那么JavaScript会调用valueOf()方法,如果存在这个方法,则JavaScript调用它,如果返回原始值,JavaScript将这个值转换成字符串(如果本身不是字符串的话),并返回字符串结果。
否则,JavaScript将无法从toString或者valueOf获得一个原始值,因此它将抛出一个类型错误异常。

JavaScript对象到数字的转换,会首先尝试使用valueOf方法:

如果对象具有valueOf()方法,后者返回一个原始值,则JavaScript将这个原始值转换成数字并返回这个数字
否则,如果对象具有toString方法,后者返回一个原始值,则JavaScript将其转换并返回
否则,JavaScript抛出一个类型错误异常。

例如:[]转换数字会被转换成0,[1,2,2]会被转换成1
数组继承valueOf,返回一个对象,不是原始值,尝试使用toString()方法,空数组返回空字符串,转换成数字为0,含有元素的数组转换成对应的字符串,转换成相应的数字。

JavaScript中的“+”运算符可以进行数学加法和字符串连接操作,如果其中一个是对象,则JavaScript使用特殊的方法将对象转换成原始值(“==”类似)。
JavaScript运算符中的类型转换根据实际情况而定,例如“-”是把两个操作数都转换成数字。
日期类是JavaScript语言核心中唯一的预先定义类型,它定义了有意义的向字符串和数字类型的转换,视情况而定。
对于所有的非日期类对象来说,对象到原始值的转换基本上都是对象到数字的转换,但是这里的转换:通过valueof和toString方法返回的原始值都将被直接使用,而不会被强制转换成数字或者字符串。
var now = new Date();
typeof(now + 1); // "string"
typeof(now - 1); // "number"
now == now.toString(); // true:日期转字符串
now > now - 1; //true:日期转换数字
3.9 变量声明
在JavaScript中,使用一个变量之前都应当声明,变量是使用var关键字来声明的:
var i;
也可以通过一个var关键字声明多个对象:
var i , sum;
还可以将变量的声明和初始赋值结合在一起:
var i = 0 , j = 1;
如果未在var声明语句中给变量指定初始值,那么这个变量在未赋值之前就是undefined。
在JavaScript中,变量可以是任意数据类型。

3.10 变量作用域
一个变量的作用域是程序源代码中定义这个变量的区域。全局变量拥有全局作用域,在JavaScript代码中的任何地方都是有定义的。在函数内声明的变量只在函数内有定义。它们是局部变量,作用域是局部的。函数参数也是局部变量,它们只在函数体内有定义。
在函数体内,局部变量的优先级高于同名的全局变量。如果在函数内声明的一个局部变量或者函数参数中带有的变量和全局变量重名,那么全局变量就会被局部变量所遮盖。

3.10.1 函数作用域和声明前提
JavaScript没有块级作用域,只有函数作用域:变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。

function test(o){
var i = 0;
if(typeof o == "object"){
var j = 0;
for(var k = 0; k < 10; k++){
}
console.log(k); // k已经定义了 输出10
}
console.log(j); // j以及定义 输出0
}
test([1,2]);
// 10 0

JavaScript的函数作用域是指函数内声明的所有变量在函数体内始终是可见的,这意味着变量在声明之前甚至已经可用,JavaScript这个特性被非正式的称为----声明前提,即在JavaScript函数里声明的所有变量(但不涉及赋值)都被“提前”至函数体的顶部。
var scope = "global";
function f(){
console.log(scope); // undefine
var scope = "local"; //变量在这赋值,但是在函数体内任何地方均是有定义的
console.log(scope); // local
}
f();

因为函数作用域的特性,局部变量在整个函数体始终是有定义的,也就是说,在函数体内局部变量遮盖住了同名全局变,但是没赋值之前均是undefined。等同于:
var scope = "global";
function f(){
var scope;
console.log(scope); // undefine
scope = "local"; //变量在这赋值,但是在函数体内任何地方均是有定义的
console.log(scope); // local
}
f();
尽量将变量声明放在函数顶部。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: