《JavaScript 闯关记》之变量和数据类型

当次用将价值保存起来以备将来应用时,便以那个赋值给一个变量,值的档次称作数据类。

变量

JavaScript
的变量是高枕无忧型的,所谓松散型就是得为此来保存任何项目的数额。换句话说,每个变量仅仅是一个用于保存值的占位符而已。定义变量时假如下要字
var 来声明的,如下所示:

var message;

顿时行代码定义了一个名叫也 message
的变量,该变量可以用来保存任何价值(像这么非经过初始化的变量,会保留一个奇特之值
undefined)。JavaScript
也支撑直接初始化变量,因此于概念变量的还要就可安装变量的价值,如下所示:

var message = "hello";

此时,变量 message 中保存了一个字符串值
"hello"。像这样初始化变量并无见面将她标志为字符串类型,因此,可以当改变量值的又修改值的品类。如下所示:

var message = "hello";
message = 100;           // 有效的语句,不好的写法

每当是事例中,变量 message 一起保存了一个字符串值
"hello",然后该值又为一个数字值100替。虽然我们不建议改变量所保存值的型,但这种操作以
JavaScript 中了可行。

有少数得注意,即使用 var
运算符定义的变量是的该作用域中之片变量。也就是说,如果当函数中行使
var 定义一个变量,那么这个变量在函数退出后即使会见被灭绝,例如:

function test(){
    var message = "hello";  // 局部变量
}
test();
console.log(message);   // 产生错误

这里,变量 message 是在函数中使用 var
定义的,是片变量。当函数被调用时,就会见创造该变量并也那个赋值。而在此之后,这个变量又见面应声被灭绝,因此例子中之生一行代码就会促成错误。不过,可以像下这样看略
var 运算符,从而开创一个全局变量:

function test(){
    message = "hello";  // 全局变量,不好的写法
}
test();
console.log(message);   // "hello"

本条例子省略了 var 运算符,因而 message
就改成了全局变量。这样,只要调用一坏 test()
函数,这个变量就发了定义,就足以当函数外部的另地方给拜到。

虽然看略 var
运算符可以定义全局变量,但立刻吗未是推荐的做法,因为在部分作用域中定义全局变量很为难保障,给未经声明的变量赋值在严格模式下会抛来
ReferenceError 错误。

数据类型

JavaScript
中有5种植简易数据类型(也号称「基本数据类」或「原始数据类型」):UndefinedNullBooleanNumberString
。还发生1种植复杂数据列 ObjectObject
本质上是由于同组无序的名值对组合的。JavaScript
不支持任何创建于定义类型的编制,所有值最终都将是上述6栽多少类有。

typeof 运算符

是因为 JavaScript
是麻木不仁型的,因此待有雷同栽手段来检测给定变量的数据类型,typeof
就是负提供这上头信息之运算符。对一个值使用 typeof
运算符可能回下列某个字符串:

  • "undefined",如果此价值不声明或曾经声明但切莫初始化。
  • "boolean",如果这个价值是布尔值。
  • "string",如果这价是字符串。
  • "number",如果是价是数值。
  • "object",如果这个价值是目标要 null
  • "function",如果这价是函数。

脚是几个利用 typeof 运算符的例子:

var message = "some string";
console.log(typeof message);     // "string"
console.log(typeof(message));    // "string"
console.log(typeof 95);          // "number"

自上述例子可以见见,typeof
运算符既好对变量使用,又足以本着许面量使用。由于 typeof
是一个运算符而休是函数,因此例子中之圆括号尽管可以使用,但连无提倡。

typeof null 结果是 "object" 是历史遗留 Bug,在 ECMAScript
6遭到,曾经有提案也历史平反, 将 type null 的值纠正吧
"null",但最终欠提案为拒。理由是历史遗留代码太多,不如继续以擦就擦。

由技术角度说,函数在 JavaScript
中凡目标,不是一律栽多少类。然而,函数也确发一部分特有之性能,因此通过
typeof 运算符来区别函数和另外对象是产生必不可少的。

恢宏阅读「为什么 JavaScript 里面 typeof null 的值是 "object"?」
https://www.zhihu.com/question/21691758

推而广之阅读「MDN 之 typeof
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/typeof

壮大阅读「JavaScript 检测原始值、引用值、属性」
http://shijiajie.com/2016/06/20/javascript-maintainable-javascript-validate1/

扩展阅读「JavaScript 检测的 basevalidate.js」
http://shijiajie.com/2016/06/25/javascript-maintainable-javascript-basevalidatejs/

Undefined 类型

Undefined 类型只出1个价,即 undefined。使用 var
声明变量但不对那加以初始化时,这个变量的价值就是
undefined,直接动用不声明的变量会发生错误。对未声明或就扬言但非初始化的变量执行
typeof 运算符会返回 "undefined" 值,例如:

var message;    // 这个变量声明之后默认取得了 undefined 值
// var age      // 这个变量并没有声明

console.log(message);           // "undefined"
console.log(age);               // 产生错误
console.log(typeof message);    // "undefined"
console.log(typeof age);        // "undefined"

Null 类型

Null 类型也止出1独价值,即 null。它因此来代表值的空缺。你得看
undefined 是表示系统级的、出乎意料的或者相近错误的价的空缺,而 null
是表示程序级的、正常的要当预料中的值的空缺。在下列场景被应该使用
null

  • 为此来初始化一个变量,这个变量可能赋值为一个对象。
  • 用来和一个既初始化的变量比较,这个变量可以是吧得以无是一个目标。
  • 当函数的参数期望是目标时,作用参数传入。
  • 当函数的归来值期待是目标时,作用返回值传出。

以下列场景中莫应有用 null

  • 不用使用 null 来检测是否传入了某个参数。
  • 并非以 null 来检测一个未初始化的变量。

Boolean 类型

Boolean 类型是 JavaScript
中动用得最多之等同栽类型,该类型只有个别只字面值:true
false。需要小心的是,他们是分轻重缓急写的,也就是说 True
False(以及任何的插花大小写形式)都未是 Boolean 值,只是标识符。

虽然 Boolean 类型的字面值只出半点独,但 JavaScript
中具备项目的值都能够利用 if 语句或 Boolean() 函数转换为相应的
Boolean 值,例如:

var message = "Hello world!";
if (message){
    console.log("Value is true.");  // 被执行
}
var messageAsBoolean = Boolean(message);
console.log(messageAsBoolean);  // true

下表给闹了各种数码类及其相应之转换规则。

数据类型 转换为true的值 转换为false的值
Undefined undefined
Null null
Boolean true false
String 任何非空字符串 ""(空字符串)
Number 任何非零数字值(包括无穷大) 0和NaN
Object 任何对象

Number 类型

Number 类型是 JavaScript 中最好令人关注之数据类型,这种类型应用 IEEE 754
格式来表示整数和浮点数值(浮点数值在一些语言中为深受名双精度数值)。和其它编程语言不同,JavaScript
中的保有数字都就此浮点数值表示。

扩张阅读「IEEE 754-1985」
https://en.wikipedia.org/wiki/IEEE\_754-1985

整数

于 JavaScript
中展开算术计算时,所有为八进制和十六进制表示的数值最终都将为更换成为十进制数值。例如:

var a = 10;         // 十进制
var b = 023;        // 八进制
var c = 0x12ac;     // 十六进制
console.log(b);     // 19
console.log(c);     // 4780

八进制第一个必须是0,后面与八上制序列0到7,如果盖了限定,则忽略前导0,后面的数值作为十进制解析,例如:089会晤于解析为89。(八上前制字面量在严厉模式下是废的,会丢弃来左。)

十六进制前少位必须是 0x 或
0X,后同十六前行制序列09、af(不分轻重缓急写),如果盖了限制,则会报语法错误。

浮点数

所谓浮点数价,就是该数值中必含有一个略带数触及,并且有点数点后面总得至少有平等个数字。虽然小数点前面可无整数,但咱不推荐这种写法。例如:

var a = 1.1;
var b = 0.1;
var c = .1;     // 有效,但不推荐

JavaScript 会不失时机的拿浮点数转换成为整数。例如:

var a = 5.;      // 解析成整数5
var b = 5.0;     // 解析成整数5

对庞或者太小的数值,可下科学技术法(也称e表示拟)。JavaScript
会将那些稍微数点后面带有6单七零八落之上之有点受1之浮点数值转换为以e表示拟表示的数值。例如:

var a = 3.14e7;             // 等于31400000
var b = 3.14E-7;            // 等于0.000000314
console.log(0.0000003);     // 3e-7

浮点数值的嵩精度是17位小数,但当展开算术计算时该精确度远远不如整数,例如:

console.log(0.1 + 0.2);     // 0.30000000000000004

这个舍入误差会招致无法测试特定的浮点数值,因此,千古不要测试某个特定的浮点数值

正无穷、负无穷

鉴于内存限制,JavaScript 能代表的数值范围从 Number.MIN_VALUE
Number.MAX_VALUE,并将超出范围的反复易成 Number.POSITIVE_INFINITY
Number.NEGATIVE_INFINITY。0作为除数是未见面报错的,正数除以0返回正无根本,负数除以0返回负无穷,0除以0返回NaN。例如:

console.log(Number.MAX_VALUE);       // 最大数 1.7976931348623157e+308
console.log(Number.MIN_VALUE);       // 最小数 5e-324

console.log(Number.POSITIVE_INFINITY);    // 正无穷  Infinity
console.log(Number.NEGATIVE_INFINITY);    // 负无穷 -Infinity

console.log( 1 / 0);     //  Infinity
console.log(-1 / 0);     // -Infinity

JavaScript 提供了 isFinite() 函数,来规定一个频凡匪是发生根的。例如:

console.log(isFinite(100));         // true
console.log(isFinite(Infinity));    // false 

NaN

NaN(not a
number),是一个异的数值。之所以称它们吧「非数值」,是以它不可知参与算数运算,任何涉及
NaN 的操作都回来 NaN。并且 NaN
与外价值都不顶(包括我)。例如:

console.log(typeof NaN);      // "number"

console.log(0 / 0);                 // NaN
console.log(NaN - NaN);             // NaN
console.log(Infinity - Infinity);   // NaN

var a = NaN;
console.log(a === a);   // false

JavaScript 提供了 isNaN() 函数,来规定一个往往凡是匪是 NaN。例如:

console.log(isNaN(100));        //  false
console.log(isNaN("100"));      //  false
console.log(isNaN(true));       //  false
console.log(isNaN("sss"));      //  true
console.log(isNaN(NaN));        //  true

Number()parseInt()parseFloat() 转型函数

isNaN() 函数在吸纳及一个值后,会尝试采用转型函数 Number()
将这价转换为数值,转换规则如下:

  • undefined 转换为 NaN
  • null 转换为 0;
  • true 转换为 1false 转换为 0
  • number 整数转换为十进制,小数不转移;
  • string
    如果单含十前行制数和小数,则归对应之数值,如果就含八前进制数,则忽略前导0返回剩余部分,如果仅仅包含十六进制,则归十向前制数,空字符串转换为0,其它字符串转换为
    NaN
  • object 先则调用对象的 valueOf()
    方法,然后按前的规则转换返回的价值。如果换的结果是
    NaN,则调用对象的 toString()
    方法,然后再次以前的条条框框转换返回的字符串值。

由于 Number()
转型函数在变字符串时莫敷好,因此还有个别单特别用来更换字符串的函数
parseInt()parseFloat() 函数。

parseInt()
函数会忽略字符串前面的空格,直至找到第一只非空格字符,只要第一独非空格字符不是数字或者正负号,一律返回
NaN, 如果第一单非空格字符是数字字符,parseInt()
会继续分析第二个字符,直到解析了所有继续字符或遇到了一个非数字字符。例如:

console.log(parseInt(""));          // NaN(Number("")返回 0)
console.log(parseInt("123S"));      // 123
console.log(parseInt("12.4"));      // 12

parseFloat()
函数也会忽视字符串前面的空格,直至找到第一只非空格字符,只要第一独非空格字符不是数字或者正负号或者小数接触,一律返回
NaN, 如果第一只非空格字符是上述字符之一,parseFloat()
会继续分析第二单字符,直到解析了所有继续字符或遇到了一个非浮点数值。例如:

console.log(parseFloat("098.2"));       // 98.2
console.log(parseFloat("123.23.23"));   // 123.23

String 类型

String 类型用于表示出于零要么多只16号 Unicode
字符组成的字符序列,即字符串。字符串可以由双引号(”)或单引号(’)表示,因此下两栽字符串的写法都是卓有成效的:

var firstName = "Nicholas";
var lastName = 'Zakas';

JavaScript
中之就片种植语法形式没有啊分别。用对引号表示的字符串和用单引号表示的字符串完全相同。不过,以对引号开头的字符串也须坐双引号结尾,而为单引号开头的字符串必须为单引号结尾。

String
数据类型包含部分奇异的字符字面量,也受转义序列,用于表示未打印字符,或者有其他用途的字符。例如:\n
换行、\t 制表、\b 空格、\r 回车、\f 进纸、\\ 斜杠、\'
单引号,在为此单引号表示的字符串中行使、\"
双引号,在于是对引号表示的字符串中使。

转义字符可出现在字符串中的人身自由位置,且长也1。如要当字符串中显 \
,则须用 \ 进行转义。例如:

console.log("\n\\".length);    // 2
console.log("\\hello");        // "\hello"(长度为6)

多数分值都好下持续而来之 toString()方换为字符串,但
undefinednull 值没有是方法。对数值使用 toString()
方法时,可以传一个数字基数,以这个输出对应进制的字符串值。例如:

console.log(true.toString());   // "true"

var num = 10;
console.log(num.toString());    // "10"
console.log(num.toString(2));   // "1010"
console.log(num.toString(8));   // "12"
console.log(num.toString(16));  // "a"

每当不了解如果转换的值是未是 undefinednull
的情形下,还可以动用转型函数
String(),这个函数能够将另项目的价值转换为字符串。String()
函数遵循下列转换规则:

  • 倘值有ECMAScript toString()
    方法,则调用该措施(没有参数)并回到相应的结果;
  • 如值是 undefined,则返回 "undefined"
  • 要值是 null,则返回 "null"

var value;
console.log(String(10));        // "10"
console.log(String(true));      // "true"
console.log(String(null));      // "null"
console.log(String(value));     // "undefined"

Object 类型

JavaScript 中保有目标都持续自 Object
类型,每个对象都抱有下列基本的特性和章程:

  • constructor:保存着用于创造当前目标的函数(构造函数)。
  • hasOwnProperty():用于检查给定的习性在时下目标实例中是不是在。
  • propertyIsEnumerable():用于检查给定的性能是否能运用for-in语句子来枚举。
  • isPrototypeOf():用于检查对象是否是流传对象的原型。
  • toString() 方法:返回对象的字符串表示。
  • toLocaleString():返回对象的地头字符串表示。
  • valueOf():返回对象的字符串、数值或布尔值表示(通常和toString()方法的归值相同)。

Object 本质上是由同样组无序的名值对组合,「名称」部分凡是一个 JavaScript
字符串,「值」部分可是另 JavaScript
的数据类型(包括对象与章程)。这如果用户可以根据现实需求,创建有一定复杂的数据结构。

以下简单栽办法还可以创建一个空对象,这半种方式以语义上是平等之。第二种植更便于的不二法门吃作「对象字面量」法。这也是
JSON 格式的基本语法,一般我们先行选项第二栽艺术。例如:

var obj = new Object();
var obj = {};   // 好的写法

「对象字面量」也堪用来当靶实例中定义一个靶:

var obj = {
    name: "Carrot",
    "for": "Max",
    details: {
        color: "orange",
        size: 12
    }
}

对象的习性可以经链式(chain)表示方法进行访问:

obj.details.color;       // orange
obj["details"]["size"];  // 12

形成创建后,对象属性可以经过如下两栽方式展开赋值和访问:

obj.name = "Simon"      // 赋值
var name = obj.name;    // 访问

obj["name"] = "Simon";  // 赋值
var name = obj["name"]; // 访问

关卡

// 挑战一
console.log(typeof "undefined");  // ???
console.log(typeof null);         // ???

// 挑战二
var message = "some string";
console.log(typeof massage);    // ???
message = 10000;
console.log(typeof message);    // ???

// 挑战三
var a;
var b = null;
var c = {};
if(a && b && c){
    console.log("true.");       // ???
}else{
    console.log("false.");      // ???
}

// 挑战四
console.log(typeof (0 / 0));    // ???
console.log(023 + 123);         // ???

// 挑战五
console.log(Number("1234S"));   // ???
console.log(parseInt("1234S")); // ???

// 挑战六
console.log(3.14E-7 === 0.000000314);   // ???
console.log(0.1 + 0.6 === 0.7); // ???
console.log(0.1 + 0.7 === 0.8); // ???
console.log(NaN === NaN);       // ???

// 挑战七
console.log("\right\now");          // ???
console.log("\right\now".length);   // ???
console.log(010.toString(2));       // ???

// 挑战八
// 1、为 person、wife、child 对象新增 weight 属性,数值分别为 62、36、15。
// 2、为 person 对象新增二胎 child2 子对象,name 为 emma,其他属性自行发挥。
var person = {
    name: "stone",
    age: 30,
    wife: {
        name: "sohpie",
        age: 30
    },
    child:{
        name: "tommy",
        age: 3
    }
}

挑战九,深度阅读下面两首文章,提出你的疑团。

「JavaScript 检测原始值、引用值、属性」
http://shijiajie.com/2016/06/20/javascript-maintainable-javascript-validate1/

「JavaScript 检测之 basevalidate.js」
http://shijiajie.com/2016/06/25/javascript-maintainable-javascript-basevalidatejs/

更多

体贴入微微信公众号「劼哥舍」回复「答案」,获取关卡详解。
关注
https://github.com/stone0090/javascript-lessons,获取最新动态。