对象的扩展
对象(object)是 JavaScript 最重要的数据结构。ES6
对它进行了重大升级,本章介绍数据结构本身的改变,下一章介绍Object对象的新增方法。
属性的简洁表示法
ES6
允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
123456const foo = 'bar';const baz = {foo};baz // {foo: "bar"}// 等同于const baz = {foo: foo};
上面代码中,变量foo直接写在大括号里面。这时,属性名就是变量名,
属性值就是变量值。下面是另一个例子。
1234567891011function f(x, y) { return {x, y};}// 等同于function f(x, y) { return {x: x, y: y};}f(1, 2) // Object {x: 1, ...
数组的扩展
扩展运算符
含义
扩展运算符(spread)是三个点(...)。它好比 rest
参数的逆运算,将一个数组转为用逗号分隔的参数序列。
12345678console.log(...[1, 2, 3])// 1 2 3console.log(1, ...[2, 3, 4], 5)// 1 2 3 4 5[...document.querySelectorAll('div')]// [<div>, <div>, <div>]
该运算符主要用于函数调用。
12345678910function push(array, ...items) { array.push(...items);}function add(x, y) { return x + y;}const numbers = [4, 38];add(...numbers) // 42
上面代码中,array.push(...items)和add(...numbers)这两行,都是函数的调用,它们都使用了扩展运算符。该运 ...
函数的扩展
函数参数的默认值
基本用法
ES6 之前,不能直接为函数的参数指定默认值,只能采用变通的方法。
12345678function log(x, y) { y = y || 'World'; console.log(x, y);}log('Hello') // Hello Worldlog('Hello', 'China') // Hello Chinalog('Hello', '') // Hello World
上面代码检查函数log的参数y有没有赋值,如果没有,则指定默认值为World。这种写法的缺点在于,如果参数y赋值了,但是对应的布尔值为false,则该赋值不起作用。就像上面代码的最后一行,参数y等于空字符,结果被改为默认值。
为了避免这个问题,通常需要先判断一下参数y是否被赋值,如果没有,再等于默认值。
123if (typeof y === 'undefined') { y = ...
数值的扩展
二进制和八进制表示法
ES6
提供了二进制和八进制数值的新的写法,分别用前缀0b(或0B)和0o(或0O)表示。
120b111110111 === 503 // true0o767 === 503 // true
从 ES5
开始,在严格模式之中,八进制就不再允许使用前缀0表示,ES6
进一步明确,要使用前缀0o表示。
12345678910// 非严格模式(function(){ console.log(0o11 === 011);})() // true// 严格模式(function(){ 'use strict'; console.log(0o11 === 011);})() // Uncaught SyntaxError: Octal literals are not allowed in strict mode.
如果要将0b和0o前缀的字符串数值转为十进制,要使用Number方法。
12Number('0b111') // 7Number('0o10 ...
正则的扩展
RegExp 构造函数
在 ES5 中,RegExp构造函数的参数有两种情况。
第一种情况是,参数是字符串,这时第二个参数表示正则表达式的修饰符(flag)。
123var regex = new RegExp('xyz', 'i');// 等价于var regex = /xyz/i;
第二种情况是,参数是一个正则表示式,这时会返回一个原有正则表达式的拷贝。
123var regex = new RegExp(/xyz/i);// 等价于var regex = /xyz/i;
但是,ES5 不允许此时使用第二个参数添加修饰符,否则会报错。
12var regex = new RegExp(/xyz/, 'i');// Uncaught TypeError: Cannot supply flags when constructing one RegExp from another
ES6
改变了这种行为。如果RegExp构造函数第一个参数是一个正则对象,那么可以使用第二个参数指定修饰符。而且,返回的正则表达式会 ...
字符串的新增方法
本章介绍字符串对象的新增方法。
String.fromCodePoint()
ES5 提供String.fromCharCode()方法,用于从 Unicode
码点返回对应字符,但是这个方法不能识别码点大于0xFFFF的字符。
12String.fromCharCode(0x20BB7)// "ஷ"
上面代码中,String.fromCharCode()不能识别大于0xFFFF的码点,所以0x20BB7就发生了溢出,最高位2被舍弃了,最后返回码点U+0BB7对应的字符,而不是码点U+20BB7对应的字符。
ES6
提供了String.fromCodePoint()方法,可以识别大于0xFFFF的字符,弥补了String.fromCharCode()方法的不足。在作用上,正好与下面的codePointAt()方法相反。
1234String.fromCodePoint(0x20BB7)// "?"String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y ...
字符串的扩展
本章介绍 ES6
对字符串的改造和增强,下一章介绍字符串对象的新增方法。
字符的 Unicode 表示法
ES6 加强了对 Unicode
的支持,允许采用\uxxxx形式表示一个字符,其中xxxx表示字符的
Unicode 码点。
12"\u0061"// "a"
但是,这种表示法只限于码点在\u0000~\uFFFF之间的字符。超出这个范围的字符,必须用两个双字节的形式表示。
12345"\uD842\uDFB7"// "?""\u20BB7"// " 7"
上面代码表示,如果直接在\u后面跟上超过0xFFFF的数值(比如\u20BB7),JavaScript
会理解成\u20BB+7。由于\u20BB是一个不可打印字符,所以只会显示一个空格,后面跟着一个7。
ES6
对这一点做出了改进,只要将码点放入大括号,就能正确解读该字符。
1234567891011"\u{20BB7}"// "?&quo ...
变量的解构赋值
数组的解构赋值
基本用法
ES6
允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
以前,为变量赋值,只能直接指定值。
123let a = 1;let b = 2;let c = 3;
ES6 允许写成下面这样。
1let [a, b, c] = [1, 2, 3];
上面代码表示,可以从数组中提取值,按照对应位置,对变量赋值。
本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。下面是一些使用嵌套数组进行解构的例子。
1234567891011121314151617181920let [foo, [[bar], baz]] = [1, [[2], 3]];foo // 1bar // 2baz // 3let [ , , third] = ["foo", "bar", "baz"];third // "baz"let [x, , y] = [1, 2, 3];x // 1y // 3let [h ...
let 和 const 命令
let 命令
基本用法
ES6
新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
1234567{ let a = 10; var b = 1;}a // ReferenceError: a is not defined.b // 1
上面代码在代码块之中,分别用let和var声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效。
for循环的计数器,就很合适使用let命令。
123456for (let i = 0; i < 10; i++) { // ...}console.log(i);// ReferenceError: i is not defined
上面代码中,计数器i只在for循环体内有效,在循环体外引用就会报错。
下面的代码如果使用var,最后输出的是10。
1234567var a = [];for (var i = 0; i ...
Object 对象
概述
JavaScript
原生提供Object对象(注意起首的O是大写),本章介绍该对象原生的各种方法。
JavaScript
的所有其他对象都继承自Object对象,即那些对象都是Object的实例。
Object对象的原生方法分成两类:Object本身的方法与Object的实例方法。
(1)Object对象本身的方法
所谓“本身的方法”就是直接定义在Object对象的方法。
1Object.print = function (o) { console.log(o) };
上面代码中,print方法就是直接定义在Object对象上。
(2)Object的实例方法
所谓实例方法就是定义在Object原型对象Object.prototype上的方法。它可以被Object实例直接使用。
123456Object.prototype.print = function () { console.log(this);};var obj = new Object();obj.print() // Object
上面代码中,Obje ...