基本语法
1. 变量和基本语法
var a = 1
// 基本相同
a = 1
上面代码需要注意的是:不写var的做法,不利于表达意图,而且容易不知不觉地创建全局变量,所以建议总是使用var命令声明变量
console.log(a)
var a = 1
JavaScript 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting)。
var a
console.log(a) //undefined
a = 1
switch (fruit) {
case "banana":
// ...
break;
case "apple":
// ...
break;
default:
// ...
}
需要注意的是,switch语句后面的表达式,与case语句后面的表示式比较运行结果时,采用的是严格相等运算符(===),而不是相等运算符(==),这意味着比较时不会发生类型转换。例如下面的代码
var x = 1;
switch (x) {
case true:
console.log('x 发生类型转换');
default:
console.log('x 没有发生类型转换');
}
// x 没有发生类型转换
break语句和continue语句都具有跳转作用,可以让代码不按既有的顺序执行。
break语句用于跳出代码块或循环。直接结束循环
continue语句用于立即终止本轮循环,返回循环结构的头部,开始下一轮循环。
var i = 0;
while (i < 100){
i++;
if (i % 2 === 0) continue;
console.log('i 当前为:' + i);
}
数据类型
数值
Number
(整数和小数)
字符串String
布尔值boolean
(true和false)
undefined
: 表示“未定义”或不存在,即由于目前没有定义,所以此处暂时没有任何值
null
: 表示空值,即此处的值为空。
对象object
各种值组成的集合
symbol
es6新增类型。方应杭:JS 中的 Symbol 是什么
var a = undefined
// 或者
var a = null
上面的写法几乎是等价的。
console.log(null == undefined)
返回的是true。
这个可以说是JavaScript的一个bug。一个历史遗留的bug。
一般的做法是。声明一个原始类型的值,并且初始不确定值,此时可以赋值undefined
。
声明一个对象时,并且没有赋值,可以先赋值null。
- JavaScript 有三种方法,可以确定一个值到底是什么类型。
typeof运算符
instanceof运算符
Object.prototype.toString方法
console.log(typeof 1) // number
console.log(typeof '1') // string
console.log(typeof true) // boolean
console.log(typeof undefiend) // undefiend
console.log(typeof null) // object // 此处是typeof的弊端之一,正常的逻辑应该是返回null。
console.log(typeof {}) // object
function f () {}
console.log(typeof f) // function // 并没有function类型,弊端
number
JavaScript 内部,所有数字都是以64位浮点数形式储存,即使整数也是如此。
由于浮点数不是精确的值,所以涉及小数的比较和运算要特别小心。
0.1 + 0.2 === 0.3
// false
0.3 / 0.1
// 2.9999999999999996
(0.3 - 0.2) === (0.2 - 0.1)
// false
数值表示法。字面量 如35,科学计数法
123e-3
// 0.123
JavaScript 对整数提供四种进制的表示方法:十进制、十六进制、八进制、二进制。
十进制:没有前导0的数值。
八进制:有前缀0o或0O的数值,或者有前导0、且只用到0-7的八个阿拉伯数字的数值。
十六进制:有前缀0x或0X的数值。
二进制:有前缀0b或0B的数值。
console.log(012345) // 5349
// 所以在存储电话号码时推荐使用字符串形式
console.log('012345') // 012345
NaN是 JavaScript 的特殊值,表示“非数字”(Not a Number)
NaN不是独立的数据类型,而是一个特殊数值,它的数据类型依然属于Number
NaN不等于任何值,包括它本身
5 - 'x' // NaN
typeof NaN // 'number'
NaN === NaN // false
Boolean(NaN) // false
parseInt(): 用于将字符串转为整数。
parseFloat(): 用于将一个字符串转为浮点数。
isNaN(): 可以用来判断一个值是否为NaN。
isFinite(): 返回一个布尔值,表示某个值是否为正常的数值。
- parseInt()
1). 如果parseInt的参数不是字符串,则会先转为字符串再转换。
2). 字符串转为整数的时候,是一个个字符依次转换,如果遇到不能转为数字的字符,就不再进行下去,返回已经转好的部分。
3). 如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN
4). parseInt方法还可以接受第二个参数(2到36之间),表示被解析的值的进制,返回该值对应的十进制数。默认为十进制
5). parseInt的返回值只有两种可能,要么是一个十进制整数,要么是NaN。
parseInt('15e2') // 15
parseInt('+') // NaN
parseInt('+1') // 1
parseInt('.3') // NaN
parseInt('1000', 2) // 8 // 二进制1000,转成十进制
parseInt('1000', 6) // 216 // 六进制1000,转成十进制
parseInt('1000', 8) // 512 // 八进制1000,转成十进制
parseInt('1546', 2) // 1
parseInt('546', 2) // NaN // 二进制数除了0,就是1。不存在546
parseInt(011, 2) // NaN
// 等同于
parseInt(String(011), 2)
// 等同于
parseInt(String(9), 2)
JavaScript 不再允许将带有前缀0的数字视为八进制数,而是要求忽略这个0。但是,为了保证兼容性,大部分浏览器并没有部署这一条规定。
- parseFloat()
parseFloat('314e-2') // 3.14
parseFloat('0.0314E+2') // 3.14
parseFloat('3.14more non-digit characters') // 3.14
parseFloat([]) // NaN
parseFloat('FF2') // NaN
- isNaN
isNaN为true的值,有可能不是NaN,而是一个字符串
isNaN(123) // false
isNaN('Hello') // true
// 相当于
isNaN(Number('Hello')) // true
isNaN({}) // true
// 等同于
isNaN(Number({})) // true
// 需要注意
isNaN([]) // false
isNaN([123]) // false
isNaN(['123']) // false
String
字符串就是零个或多个排在一起的字符,放在单引号或双引号之中
单引号字符串的内部,可以使用双引号。双引号字符串的内部,可以使用单引号。
如果要在单引号字符串的内部,使用单引号,就必须在内部的单引号前面加上反斜杠,用来转义。双引号字符串内部使用双引号,也是如此。
反斜杠(\)在字符串内有特殊含义,用来表示一些特殊字符,所以又称为转义符。
\0 :null(\u0000)
\b :后退键(\u0008)
\f :换页符(\u000C)
\n :换行符(\u000A)
\r :回车键(\u000D)
\t :制表符(\u0009)
\v :垂直制表符(\u000B)
' :单引号(\u0027)
" :双引号(\u0022)
\ :反斜杠(\u005C)
btoa():任意值转为 Base64 编码
atob():Base64 编码转为原来的值。
这两个方法不适合非 ASCII 码的字符,会报错。
var string = 'Hello World!';
btoa(string) // "SGVsbG8gV29ybGQh"
atob('SGVsbG8gV29ybGQh') // "Hello World!"
//
btoa('你好') // 报错
function b64Encode(str) {
return btoa(encodeURIComponent(str));
}
function b64Decode(str) {
return decodeURIComponent(atob(str));
}
b64Encode('你好') // "JUU0JUJEJUEwJUU1JUE1JUJE"
b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE') // "你好"
对象
对象就是一组“键值对”(key-value)的集合,是一种无序的复合数据集合
对象的所有键名都是字符串(ES6 又引入了 Symbol 值也可以作为键名),所以加不加引号都可以。
如果键名是数值,会被自动转为字符串。
如果键名不符合标识名的条件(比如第一个字符为数字,或者含有空格或运算符),且也不是数字,则必须加上引号,否则会报错。
var obj = {
'foo': 'Hello',
'bar': 'World',
1: 'a',
3.2: 'b',
1e2: true,
}
obj['100'] //true
// 报错
var obj = {
1p: 'Hello World'
}
// 不报错
var obj = {
'1p': 'Hello World',
'h w': 'Hello World',
'p+q': 'Hello World'
}
读取对象的属性,有两种方法,一种是使用点运算符,还有一种是使用方括号运算符。
请注意,如果使用方括号运算符,键名必须放在引号里面,否则会被当作变量处理。
查看一个对象本身的所有属性,可以使用Object.keys方法。
var obj = {
key1: 1,
key2: 2
};
Object.keys(obj);
// ['key1', 'key2']
delete命令用于删除对象的属性,删除成功后返回true。
注意,删除一个不存在的属性,delete不报错,而且返回true。
只有一种情况,delete命令会返回false,那就是该属性存在,且不得删除。
delete命令只能删除对象本身的属性,无法删除继承的属性
var obj = { p: 1 };
Object.keys(obj) // ["p"]
delete obj.p // true
obj.p // undefined
Object.keys(obj) // []
//
var obj = {};
delete obj.toString // true
obj.toString // function toString() { [native code] }
in运算符用于检查对象是否包含某个属性(注意,检查的是键名,不是键值),如果包含就返回true,否则返回false。
in运算符的一个问题是,它不能识别哪些属性是对象自身的,哪些属性是继承的。
var obj = { p: 1 };
'p' in obj // true
var obj = {};
'toString' in obj // true
for...in循环用来遍历一个对象的全部属性。
它遍历的是对象所有可遍历(enumerable)的属性,会跳过不可遍历的属性。
它不仅遍历对象自身的属性,还遍历继承的属性。
var obj = {};
// toString 属性是存在的
obj.toString // toString() { [native code] } // 默认不可遍历
for (var p in obj) {
console.log(p);
} // 没有任何输出
hasOwnProperty
方法用于确定属性是否是自身属性
var person = { name: '老张' };
for (var key in person) {
if (person.hasOwnProperty(key)) {
console.log(key);
}
}
// name