请人做网站收费多少,网站开发 石家庄,网站做百度小程序改造的好处,网站服务器租用注意事项这实际上说明#xff0c;对象的解构赋值是下面形式的简写。
let { foo: foo, bar: bar } { foo: ‘aaa’, bar: ‘bbb’ };
也就是说#xff0c;对象的解构赋值的内部机制#xff0c;是先找到同名属性#xff0c;然后再赋给对应的变量。真正被赋值的是后者#xff0c;而…这实际上说明对象的解构赋值是下面形式的简写。
let { foo: foo, bar: bar } { foo: ‘aaa’, bar: ‘bbb’ };
也就是说对象的解构赋值的内部机制是先找到同名属性然后再赋给对应的变量。真正被赋值的是后者而不是前者。
let { foo: baz } { foo: ‘aaa’, bar: ‘bbb’ };
baz // “aaa”
foo // error: foo is not defined
上面代码中foo是匹配的模式baz才是变量。真正被赋值的是变量baz而不是模式foo。
2嵌套对象的解构赋值
与数组一样解构也可以用于嵌套结构的对象。
let obj {
p: [
‘Hello’,
{ y: ‘World’ }
]
};
let { p: [x, { y }] } obj;
x // “Hello”
y // “World”
注意这时p是模式不是变量因此不会被赋值。如果p也要作为变量赋值可以写成下面这样。
let obj {
p: [
‘Hello’,
{ y: ‘World’ }
]
};
let { p, p: [x, { y }] } obj;
x // “Hello”
y // “World”
p // [“Hello”, {y: “World”}]
下面是另一个例子。
4.5、解构赋值注意事项
1如果要将一个已经声明的变量用于解构赋值必须非常小心。
// 错误的写法
let x;
{x} {x: 1};
// SyntaxError: syntax error
上面代码的写法会报错因为 JavaScript 引擎会将{x}理解成一个代码块从而发生语法错误。只有不将大括号写在行首避免 JavaScript 将其解释为代码块才能解决这个问题。
// 正确的写法
let x;
({x} {x: 1});
上面代码将整个解构赋值语句放在一个圆括号里面就可以正确执行。关于圆括号与解构赋值的关系参见下文。
2解构赋值允许等号左边的模式之中不放置任何变量名。因此可以写出非常古怪的赋值表达式。
({} [true, false]);
({} ‘abc’);
({} []);
上面的表达式虽然毫无意义但是语法是合法的可以执行。
3由于数组本质是特殊的对象因此可以对数组进行对象属性的解构。
let arr [1, 2, 3];
let {0 : first, [arr.length - 1] : last} arr;
first // 1
last // 3
上面代码对数组进行对象解构。数组arr的0键对应的值是1[arr.length - 1]就是2键对应的值是3。方括号这种写法属于“属性名表达式”。
4.6、解构赋值的用途
变量的解构赋值用途很多。
1交换变量的值
let x 1;
let y 2;
[x, y] [y, x];
上面代码交换变量x和y的值这样的写法不仅简洁而且易读语义非常清晰。
2从函数返回多个值
函数只能返回一个值如果要返回多个值只能将它们放在数组或对象里返回。有了解构赋值取出这些值就非常方便。
// 返回一个数组
function example() {
return [1, 2, 3];
}
let [a, b, c] example();
// 返回一个对象
function example() {
return {
foo: 1,
bar: 2
};
}
let { foo, bar } example();
3函数参数的定义
解构赋值可以方便地将一组参数与变量名对应起来。
// 参数是一组有次序的值
function f([x, y, z]) { … }
f([1, 2, 3]);
// 参数是一组无次序的值
function f({x, y, z}) { … }
f({z: 3, y: 2, x: 1});
4提取JSON数据
解构赋值对提取 JSON 对象中的数据尤其有用。
let jsonData {
id: 42,
status: “OK”,
data: [867, 5309]
};
let { id, status, data: number } jsonData;
console.log(id, status, number);
// 42, “OK”, [867, 5309]
上面代码可以快速提取 JSON 数据的值。
5函数参数的默认值
jQuery.ajax function (url, {
async true,
beforeSend function () {},
cache true,
complete function () {},
crossDomain false,
global true,
// … more config
} {}) {
// … do stuff
};
指定参数的默认值就避免了在函数体内部再写var foo config.foo || ‘default foo’;这样的语句。
6遍历Map结构
任何部署了 Iterator 接口的对象都可以用for…of循环遍历。Map 结构原生支持 Iterator 接口配合变量的解构赋值获取键名和键值就非常方便。
const map new Map();
map.set(‘first’, ‘hello’);
map.set(‘second’, ‘world’);
for (let [key, value] of map) {
console.log(key is value);
}
// first is hello
// second is world
如果只想获取键名或者只想获取键值可以写成下面这样。
// 获取键名
for (let [key] of map) {
// …
}
// 获取键值
for (let [,value] of map) {
// …
}
7输入模块的指定方法
加载模块时往往需要指定输入哪些方法。解构赋值使得输入语句非常清晰。
const { SourceMapConsumer, SourceNode } require(“source-map”);
5、字符串、函数、数组、对象的扩展 5.1、模板字符串
传统的 JavaScript 语言输出模板通常是这样写的下面使用了 jQuery 的方法。
$(‘#result’).append(
‘There are ’ basket.count ’
items in your basket, ’
‘’ basket.onSale
‘ are on sale!’
);
上面这种写法相当繁琐不方便ES6 引入了模板字符串解决这个问题。
$(‘#result’).append(
There are ${basket.count} items
in your basket, ${basket.onSale}
are on sale!
);
模板字符串template string是增强版的字符串用反引号标识。它可以当作普通字符串使用也可以用来定义多行字符串或者在字符串中嵌入变量。
// 普通字符串
In JavaScript \n is a line-feed.
// 多行字符串
In JavaScript this is
not legal.
console.log(string text line 1
string text line 2);
// 字符串中嵌入变量
let name “Bob”, time “today”;
Hello ${name}, how are you ${time}?
上面代码中的模板字符串都是用反引号表示。
转义符号
如果在模板字符串中需要使用反引号则前面要用反斜杠转义。
let greeting \Yo World!;
多行字符串
如果使用模板字符串表示多行字符串所有的空格和缩进都会被保留在输出之中。
$(‘#list’).html( firstsecond);
上面代码中所有模板字符串的空格和换行都是被保留的比如 ul 标签前面会有一个换行。如果你不想要这个换行可以使用 trim 方法消除它。
$(‘#list’).html( firstsecond.trim());
插入变量
模板字符串中嵌入变量需要将变量名写在${}之中。
function authorize(user, action) {
if (!user.hasPrivilege(action)) {
throw new Error(
// 传统写法为
// User ’
// user.name
// ’ is not authorized to do ’
// action
// ‘.’
User ${user.name} is not authorized to do ${action}.);
}
}
插入表达式
大括号内部可以放入任意的 JavaScript 表达式可以进行运算以及引用对象属性。
let x 1;
let y 2;
${x} ${y} ${x y}
// “1 2 3”
${x} ${y * 2} ${x y * 2}
// “1 4 5”
let obj {x: 1, y: 2};
${obj.x obj.y}
// “3”
调用函数
模板字符串之中还能调用函数。
function fn() {
return “Hello World”;
}
foo ${fn()} bar
// foo Hello World bar
如果大括号中的值不是字符串将按照一般的规则转为字符串。比如大括号中是一个对象将默认调用对象的 toString 方法。
如果模板字符串中的变量没有声明将报错。
// 变量place没有声明
let msg Hello, ${place};
// 报错
由于模板字符串的大括号内部就是执行 JavaScript 代码因此如果大括号内部是一个字符串将会原样输出。
Hello ${World}
// “Hello World”
注意要点
模板字符串中的换行和空格都是会被保留的
innerHtml menumine;
console.log(innerHtml);
// 输出 menumine5.2、字符串扩展方法
1子串的识别
ES6 之前判断字符串是否包含子串用 indexOf 方法ES6 新增了子串的识别方法。 includes()返回布尔值判断是否找到参数字符串。 startsWith()返回布尔值判断参数字符串是否在原字符串的头部。 endsWith()返回布尔值判断参数字符串是否在原字符串的尾部。
以上三个方法都可以接受两个参数需要搜索的字符串和可选的搜索起始位置索引。
let s ‘Hello world!’;
s.startsWith(‘Hello’) // true
s.endsWith(‘!’) // true
s.includes(‘o’) // true
这三个方法都支持第二个参数表示开始搜索的位置。
let s ‘Hello world!’;
s.startsWith(‘world’, 6) // true
s.endsWith(‘Hello’, 5) // true
s.includes(‘Hello’, 6) // false
上面代码表示使用第二个参数 n 时 endsWith 的行为与其他两个方法有所不同。它针对前 n 个字符而其他两个方法针对从第 n 个位置直到字符串结束。
注意点 这三个方法只返回布尔值如果需要知道子串的位置还是得用 indexOf 和 lastIndexOf 。 这三个方法如果传入了正则表达式而不是字符串会抛出错误。而 indexOf 和 lastIndexOf 这两个方法它们会将正则表达式转换为字符串并搜索它。
2字符串重复
repeat()返回新的字符串表示将字符串重复指定次数返回。
‘x’.repeat(3) // “xxx”
‘hello’.repeat(2) // “hellohello”
‘na’.repeat(0) // “”
参数如果是小数会被向下取整。
‘na’.repeat(2.9) // “nana”
如果 repeat 的参数是负数或者 Infinity 会报错。
‘na’.repeat(Infinity)
// RangeError
‘na’.repeat(-1)
// RangeError
但是如果参数是 0 到-1 之间的小数则等同于 0这是因为会先进行取整运算。0 到-1 之间的小数取整以后等于 -0 repeat 视同为 0。
‘na’.repeat(-0.9) // “”
参数 NaN 等同于 0。
‘na’.repeat(NaN) // “”
如果 repeat 的参数是字符串则会先转换成数字。
‘na’.repeat(‘na’) // “”
‘na’.repeat(‘3’) // “nanana”
3字符串补全
ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度会在头部或尾部补全。 padStart返回新的字符串表示用参数字符串从头部左侧补全原字符串。 padEnd返回新的字符串表示用参数字符串从尾部右侧补全原字符串。
以上两个方法接受两个参数第一个参数是指定生成的字符串的最小长度第二个参数是用来补全的字符串。如果没有指定第二个参数默认用空格填充。
console.log(“h”.padStart(5,“o”)); // “ooooh”
console.log(“h”.padEnd(5,“o”)); // “hoooo”
console.log(“h”.padStart(5)); // h
console.log(‘x’.padStart(5, ‘ab’)); // ‘ababx’
console.log(‘x’.padStart(4, ‘ab’)); // ‘abax’
console.log(‘x’.padEnd(5, ‘ab’)); // ‘xabab’
console.log(‘x’.padEnd(4, ‘ab’)); // ‘xaba’
上面代码中 padStart() 和 padEnd() 一共接受两个参数第一个参数是字符串补全生效的最大长度第二个参数是用来补全的字符串。
如果指定的长度小于或者等于原字符串的长度则返回原字符串:
console.log(“hello”.padStart(5,“A”)); // “hello”
如果原字符串加上补全字符串长度大于指定长度则截去超出位数的补全字符串:
console.log(“hello”.padEnd(10,“,world!”)); // “hello,worl”
如果省略第二个参数默认使用空格补全长度。
console.log(‘x’.padStart(4)); // ’ x’
console.log(‘x’.padEnd(4)); // x ’
padStart()的常见用途是为数值补全指定位数。下面代码生成 10 位的数值字符串。
console.log(‘1’.padStart(10, ‘0’)); // “0000000001”
console.log(‘12’.padStart(10, ‘0’)); // “0000000012”
console.log(‘123456’.padStart(10, ‘0’)); // “0000123456”
另一个用途是提示字符串格式。
console.log(‘12’.padStart(10, ‘YYYY-MM-DD’)); // “YYYY-MM-12”
console.log(‘09-12’.padStart(10, ‘YYYY-MM-DD’)); // “YYYY-09-12”
4消除空格
ES6对字符串实例新增了 trimStart() 和 trimEnd() 这两个方法。它们的行为与 trim() 一致trimStart() 消除字符串头部的空格trimEnd() 消除尾部的空格。它们返回的都是新字符串不会修改原始字符串。
const s ’ abc ;
s.trim() // “abc”
s.trimStart() // abc
s.trimEnd() // abc
上面代码中trimStart() 只消除头部的空格保留尾部的空格。trimEnd() 也是类似行为。
除了空格键这两个方法对字符串头部或尾部的 tab 键、换行符等不可见的空白符号也有效。
浏览器还部署了额外的两个方法trimLeft() 是 trimStart() 的别名trimRight() 是 trimEnd() 的别名。
5.3、函数的扩展
1默认值
ES6 之前不能直接为函数的参数指定默认值只能采用变通的方法。
function log(x, y) {
y y || ‘World’;
console.log(x, y);
}
log(‘Hello’) // Hello World
log(‘Hello’, ‘China’) // Hello China
log(‘Hello’, ‘’) // Hello World
上面代码检查函数log的参数y有没有赋值如果没有则指定默认值为World。这种写法的缺点在于如果参数y赋值了但是对应的布尔值为false则该赋值不起作用。就像上面代码的最后一行参数y等于空字符结果被改为默认值。
为了避免这个问题通常需要先判断一下参数y是否被赋值如果没有再等于默认值。
if (typeof y ‘undefined’) {
y ‘World’;
}
ES6 允许为函数的参数设置默认值即直接写在参数定义的后面。
function log(x, y ‘World’) {
console.log(x, y);
}
log(‘Hello’) // Hello World
log(‘Hello’, ‘China’) // Hello China
log(‘Hello’, ‘’) // Hello
可以看到ES6 的写法比 ES5 简洁许多而且非常自然。下面是另一个例子。
function Point(x 0, y 0) {
this.x x;
this.y y;
}
const p new Point();
p // { x: 0, y: 0 }
除了简洁ES6 的写法还有两个好处首先阅读代码的人可以立刻意识到哪些参数是可以省略的不用查看函数体或文档其次有利于将来的代码优化即使未来的版本在对外接口中彻底拿掉这个参数也不会导致以前的代码无法运行。
参数变量是默认声明的所以不能用let或const再次声明。
function foo(x 5) {
let x 1; // error
const x 2; // error
}
上面代码中参数变量x是默认声明的在函数体中不能用let或const再次声明否则会报错。
使用参数默认值时函数不能有同名参数。
// 不报错
function foo(x, x, y) {
// …
}
// 报错
function foo(x, x, y 1) {
// …
}
// SyntaxError: Duplicate parameter name not allowed in this context
另外一个容易忽略的地方是参数默认值不是传值的而是每次都重新计算默认值表达式的值。也就是说参数默认值是惰性求值的。
let x 99;
function foo(p x 1) {
console.log§;
}
foo() // 100
x 100;
foo() // 101
上面代码中参数p的默认值是x 1。这时每次调用函数foo都会重新计算x 1而不是默认p等于 100。
2不定参数
不定参数用来表示不确定参数个数形如…变量名由…加上一个具名参数标识符组成。具名参数只能放在参数组的最后并且有且只有一个不定参数。
基本用法
function f(…values){
console.log(values.length);
}
f(1,2); //2
f(1,2,3,4); //4
3箭头函数
箭头函数提供了一种更加简洁的函数书写方式。基本语法是
参数 函数体
基本用法
var f v v;
//等价于
var f function(a){
return a;
}
f(1); //1
当箭头函数没有参数或者有多个参数要用 () 括起来。
var f (a,b) ab;
f(6,2); //8
当箭头函数函数体有多行语句用 {} 包裹起来表示代码块当只有一行语句并且需要返回结果时可以省略 {} , 结果会自动返回。
var f (a,b) {
let result ab;
return result;
}
f(6,2); // 8
当箭头函数要返回对象的时候为了区分于代码块要用 () 将对象包裹起来
// 报错
var f (id,name) {id: id, name: name};
f(6,2); // SyntaxError: Unexpected token :
// 不报错
var f (id,name) ({id: id, name: name});
f(6,2); // {id: 6, name: 2}
注意点没有 this、super、arguments 和 new.target 绑定。
var func () {
// 箭头函数里面没有 this 对象
// 此时的 this 是外层的 this 对象即 Window
console.log(this)
}
func(55) // Window
var func () {
console.log(arguments)
}
func(55); // ReferenceError: arguments is not defined
箭头函数体中的 this 对象是定义函数时的对象而不是使用函数时的对象。
function fn(){
setTimeout((){
// 定义时this 绑定的是 fn 中的 this 对象
console.log(this.a);
},0)
}
var a 20;
// fn 的 this 对象为 {a: 19}
fn.call({a: 18}); // 18
不可以作为构造函数也就是不能使用 new 命令否则会报错
5.4、数组的扩展
1扩展运算符
扩展运算符spread是三个点...。它好比 rest 参数的逆运算将一个数组转为用逗号分隔的参数序列。
console.log(…[1, 2, 3])
// 1 2 3
console.log(1, …[2, 3, 4], 5)
// 1 2 3 4 5
[…document.querySelectorAll(‘div’)]
// [
, , ] 该运算符主要用于函数调用。
function 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)这两行都是函数的调用它们都使用了扩展运算符。该运算符将一个数组变为参数序列。
2扩展运算符的应用
复制数组
数组是复合的数据类型直接复制的话只是复制了指向底层数据结构的指针而不是克隆一个全新的数组。
const a1 [1, 2];
const a2 a1;
a2[0] 2;
a1 // [2, 2]
上面代码中a2并不是a1的克隆而是指向同一份数据的另一个指针。修改a2会直接导致a1的变化。
ES5 只能用变通方法来复制数组。
const a1 [1, 2];
const a2 a1.concat();
a2[0] 2;
a1 // [1, 2]
上面代码中a1会返回原数组的克隆再修改a2就不会对a1产生影响。
扩展运算符提供了复制数组的简便写法。
const a1 [1, 2];
// 写法一
const a2 […a1];
// 写法二
const […a2] a1;
上面的两种写法a2都是a1的克隆。
合并数组
扩展运算符提供了数组合并的新写法。
const arr1 [‘a’, ‘b’];
const arr2 [‘c’];
const arr3 [‘d’, ‘e’];
// ES5 的合并数组
arr1.concat(arr2, arr3);
// [ ‘a’, ‘b’, ‘c’, ‘d’, ‘e’ ]
// ES6 的合并数组
[…arr1, …arr2, …arr3]
// [ ‘a’, ‘b’, ‘c’, ‘d’, ‘e’ ]
不过这两种方法都是浅拷贝使用的时候需要注意。
const a1 [{ foo: 1 }];
const a2 [{ bar: 2 }];
const a3 a1.concat(a2);
const a4 […a1, …a2];
a3[0] a1[0] // true
a4[0] a1[0] // true
上面代码中a3和a4是用两种不同方法合并而成的新数组但是它们的成员都是对原数组成员的引用这就是浅拷贝。如果修改了原数组的成员会同步反映到新数组。
3数组实例的find()和findIndex()
数组实例的find方法用于找出第一个符合条件的数组成员。它的参数是一个回调函数所有数组成员依次执行该回调函数直到找出第一个返回值为true的成员然后返回该成员。如果没有符合条件的成员则返回undefined。
[1, 4, -5, 10].find((n) n 0)
// -5
上面代码找出数组中第一个小于 0 的成员。
[1, 5, 10, 15].find(function(value, index, arr) {
return value 9;
}) // 10
上面代码中find方法的回调函数可以接受三个参数依次为当前的值、当前的位置和原数组。
数组实例的findIndex方法的用法与find方法非常类似返回第一个符合条件的数组成员的位置如果所有成员都不符合条件则返回-1。
[1, 5, 10, 15].findIndex(function(value, index, arr) {
return value 9;
}) // 2
5.5、对象的扩展
ES6 允许在大括号里面直接写入变量和函数作为对象的属性和方法。这样的书写更加简洁。
const foo ‘bar’;
const baz {foo};
baz // {foo: “bar”}
// 等同于const baz {foo: foo};
除了属性简写方法也可以简写。
const o {
method() {
return “Hello!”;
}
};
// 等同于
const o {
method: function() {
return “Hello!”;
}
};
对象的新方法
Object.assign(target, source_1, ···)
用于将源对象的所有可枚举属性复制到目标对象中。
基本用法
let target {a: 1};
let object2 {b: 2};
let object3 {c: 3};
Object.assign(target,object2,object3); // 第一个参数是目标对象后面的参数是源对象
target; // {a: 1, b: 2, c: 3}
6、Class基本使用和继承 6.1、类的由来
JavaScript 语言中生成实例对象的传统方法是通过构造函数。下面是一个例子。
function Point(x, y) {
this.x x;
this.y y;
}
Point.prototype.toString function () {
return ‘(’ this.x , ’ this.y ‘)’;
};
var p new Point(1, 2);
上面这种写法跟传统的面向对象语言比如 C 和 Java差异很大很容易让新学习这门语言的程序员感到困惑。
ES6 提供了更接近传统语言的写法引入了 Class类这个概念作为对象的模板。通过class关键字可以定义类。
基本上ES6 的class可以看作只是一个语法糖它的绝大部分功能ES5 都可以做到新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。上面的代码用 ES6 的class改写就是下面这样。
class Point {
constructor(x, y) {
this.x x;
this.y y;
}
toString() {
return ‘(’ this.x , ’ this.y ‘)’;
}
}
上面代码定义了一个“类”可以看到里面有一个constructor方法这就是构造方法而this关键字则代表实例对象。也就是说ES5 的构造函数Point对应 ES6 的Point类的构造方法。
Point类除了构造方法还定义了一个toString方法。注意定义“类”的方法的时候前面不需要加上function这个关键字直接把函数定义放进去了就可以了。另外方法之间不需要逗号分隔加了会报错。
6.2、constructor方法
constructor方法是类的默认方法通过new命令生成对象实例时自动调用该方法。一个类必须有constructor方法如果没有显式定义一个空的constructor方法会被默认添加。
class Point {
}
// 等同于
class Point {
constructor() {}
}
上面代码中定义了一个空的类PointJavaScript 引擎会自动为它添加一个空的constructor方法。
6.3、类的实例
生成类的实例的写法与 ES5 完全一样也是使用new命令。前面说过如果忘记加上new像函数那样调用Class将会报错。
class Point {
// …
}
// 报错
var point Point(2, 3);
// 正确
var point new Point(2, 3);
6.4、类的继承
Class 可以通过extends关键字实现继承这比 ES5 的通过修改原型链实现继承要清晰和方便很多。
class Point {
}
class ColorPoint extends Point {
}
super关键字
super这个关键字既可以当作函数使用也可以当作对象使用。在这两种情况下它的用法完全不同。
第一种情况super作为函数调用时代表父类的构造函数。ES6 要求子类的构造函数必须执行一次super函数。
class A {}
class B extends A {
constructor() {
super();
}
}
上面代码中子类B的构造函数之中的super()代表调用父类的构造函数。这是必须的否则 JavaScript 引擎会报错。
第二种情况super作为对象时在普通方法中指向父类的原型对象在静态方法中指向父类。
class A {
p() {
return 2;
}
}
class B extends A {
constructor() {
super();
console.log(super.p()); // 2
}
}
let b new B();
上面代码中子类B当中的super.p()就是将super当作一个对象使用。这时super在普通方法之中指向A.prototype所以super.p()就相当于A.prototype.p()。
6.5、静态方法
类相当于实例的原型所有在类中定义的方法都会被实例继承。如果在一个方法前加上static关键字就表示该方法不会被实例继承而是直接通过类来调用这就称为“静态方法”。
class Foo {
static classMethod() {
return ‘hello’;
}
}
Foo.classMethod() // ‘hello’
var foo new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function
上面代码中Foo类的classMethod方法前有static关键字表明该方法是一个静态方法可以直接在Foo类上调用Foo.classMethod()而不是在Foo类的实例上调用。如果在实例上调用静态方法会抛出一个错误表示不存在该方法。
6.6、静态属性
静态属性指的是 Class 本身的属性即Class.propName而不是定义在实例对象this上的属性。
class Foo {
}
Foo.prop 1;
Foo.prop // 1
上面的写法为Foo类定义了一个静态属性prop。
目前只有这种写法可行因为 ES6 明确规定Class 内部只有静态方法没有静态属性。现在有一个提案提供了类的静态属性写法是在实例属性的前面加上static关键字。
class MyClass {
static myStaticProp 42;
constructor() {
console.log(MyClass.myStaticProp); // 42
}
}
这个新写法大大方便了静态属性的表达。
// 老写法
class Foo {
// …
}
Foo.prop 1;
// 新写法
class Foo {
static prop 1;
}
上面代码中老写法的静态属性定义在类的外部。整个类生成以后再生成静态属性。这样让人很容易忽略这个静态属性也不符合相关代码应该放在一起的代码组织原则。另外新写法是显式声明declarative而不是赋值处理语义更好。
7、Set和Map数据结构 7.1、Set
ES6 提供了新的数据结构 Set。它类似于数组但是成员的值都是唯一的没有重复的值。
基础用法
let mySet new Set();
mySet.add(1); // Set(1) {1}
mySet.add(5); // Set(2) {1, 5}
mySet.add(5); // Set(2) {1, 5} 这里体现了值的唯一性
mySet.add(“some text”);
// Set(3) {1, 5, “some text”} 这里体现了类型的多样性
var o {a: 1, b: 2};
mySet.add(o);
mySet.add({a: 1, b: 2});
// Set(5) {1, 5, “some text”, {…}, {…}}
// 这里体现了对象之间引用不同不恒等即使值相同Set 也能存储
上面代码通过add()方法向 Set 结构加入成员结果表明 Set 结构不会添加重复的值。
Set函数可以接受一个数组或者具有 iterable 接口的其他数据结构作为参数用来初始化。
// 例一
const set new Set([1, 2, 3, 4, 4]);
[…set]
// [1, 2, 3, 4]
// 例二
const items new Set([1, 2, 3, 4, 5, 5, 5, 5]);
items.size // 5
数据类型转换
Array与Set类型转换
// Array 转 Set
var mySet new Set([“value1”, “value2”, “value3”]);
// 用…操作符将 Set 转 Array
var myArray […mySet];
//Array.from方法可以将 Set 结构转为数组。
const items new Set([1, 2, 3, 4, 5]);
const array Array.from(items);
String与Set类型转换
// String 转 Set
var mySet new Set(‘hello’); // Set(4) {“h”, “e”, “l”, “o”}
// 注Set 中 toString 方法是不能将 Set 转换成 String
Set实例的属性 Set.prototype.constructor构造函数默认就是Set函数。 Set.prototype.size返回Set实例的成员总数。
Set实例的操作方法 Set.prototype.add(value)添加某个值返回 Set 结构本身。 Set.prototype.delete(value)删除某个值返回一个布尔值表示删除是否成功。 Set.prototype.has(value)返回一个布尔值表示该值是否为Set的成员。 Set.prototype.clear()清除所有成员没有返回值。
代码示例
s.add(1).add(2).add(2);
// 注意2被加入了两次
s.size // 2
s.has(1) // true
s.has(2) // true
s.has(3) // false
s.delete(2);
s.has(2) // false
Set实例的遍历方法 Set.prototype.keys()返回键名的遍历器 Set.prototype.values()返回键值的遍历器 Set.prototype.entries()返回键值对的遍历器 Set.prototype.forEach()使用回调函数遍历每个成员
需要特别指出的是Set的遍历顺序就是插入顺序。这个特性有时非常有用比如使用 Set 保存一个回调函数列表调用时就能保证按照添加顺序调用。
代码示例
keys方法、values方法、entries方法返回的都是遍历器对象详见《Iterator 对象》一章。由于 Set 结构没有键名只有键值或者说键名和键值是同一个值所以keys方法和values方法的行为完全一致。
let set new Set([‘red’, ‘green’, ‘blue’]);
for (let item of set.keys()) {
console.log(item);
}
// red
// green
// blue
for (let item of set.values()) {
console.log(item);
}
// red
// green
// blue
for (let item of set.entries()) {
console.log(item);
}
// [“red”, “red”]
// [“green”, “green”]
// [“blue”, “blue”]
forEach()代码示例
let set new Set([1, 4, 9]);
set.forEach((value, key) console.log(key ’ : ’ value))
// 1 : 1
// 4 : 4
// 9 : 9
遍历的应用
1数组去重
var mySet new Set([1, 2, 3, 4, 4]);
[…mySet]; // [1, 2, 3, 4]
2并集
var a new Set([1, 2, 3]);
var b new Set([4, 3, 2]);
var union new Set([…a, …b]); // {1, 2, 3, 4}
3交集
var a new Set([1, 2, 3]);
var b new Set([4, 3, 2]);
var intersect new Set([…a].filter(x b.has(x))); // {2, 3}
4差集
var a new Set([1, 2, 3]);
var b new Set([4, 3, 2]);
var difference new Set([…a].filter(x !b.has(x))); // {1}
7.2、Map
Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。
基本用法
const m new Map();
const o {p: ‘Hello World’};
m.set(o, ‘content’)
m.get(o) // “content”
m.has(o) // true
m.delete(o) // true
m.has(o) // false
Map中的key
key是字符串
var myMap new Map();
var keyString “a string”;
myMap.set(keyString, “和键’a string’关联的值”);
myMap.get(keyString); // “和键’a string’关联的值”
myMap.get(“a string”); // “和键’a string’关联的值”
// 因为 keyString ‘a string’
key是对象
ajax
1)ajax请求的原理/ 手写一个ajax请求 2)readyState 3)ajax异步与同步的区别 4)ajax传递中文用什么方法 , “e”, “l”, “o”}
// 注Set 中 toString 方法是不能将 Set 转换成 String
Set实例的属性 Set.prototype.constructor构造函数默认就是Set函数。 Set.prototype.size返回Set实例的成员总数。
Set实例的操作方法 Set.prototype.add(value)添加某个值返回 Set 结构本身。 Set.prototype.delete(value)删除某个值返回一个布尔值表示删除是否成功。 Set.prototype.has(value)返回一个布尔值表示该值是否为Set的成员。 Set.prototype.clear()清除所有成员没有返回值。
代码示例
s.add(1).add(2).add(2);
// 注意2被加入了两次
s.size // 2
s.has(1) // true
s.has(2) // true
s.has(3) // false
s.delete(2);
s.has(2) // false
Set实例的遍历方法 Set.prototype.keys()返回键名的遍历器 Set.prototype.values()返回键值的遍历器 Set.prototype.entries()返回键值对的遍历器 Set.prototype.forEach()使用回调函数遍历每个成员
需要特别指出的是Set的遍历顺序就是插入顺序。这个特性有时非常有用比如使用 Set 保存一个回调函数列表调用时就能保证按照添加顺序调用。
代码示例
keys方法、values方法、entries方法返回的都是遍历器对象详见《Iterator 对象》一章。由于 Set 结构没有键名只有键值或者说键名和键值是同一个值所以keys方法和values方法的行为完全一致。
let set new Set([‘red’, ‘green’, ‘blue’]);
for (let item of set.keys()) {
console.log(item);
}
// red
// green
// blue
for (let item of set.values()) {
console.log(item);
}
// red
// green
// blue
for (let item of set.entries()) {
console.log(item);
}
// [“red”, “red”]
// [“green”, “green”]
// [“blue”, “blue”]
forEach()代码示例
let set new Set([1, 4, 9]);
set.forEach((value, key) console.log(key ’ : ’ value))
// 1 : 1
// 4 : 4
// 9 : 9
遍历的应用
1数组去重
var mySet new Set([1, 2, 3, 4, 4]);
[…mySet]; // [1, 2, 3, 4]
2并集
var a new Set([1, 2, 3]);
var b new Set([4, 3, 2]);
var union new Set([…a, …b]); // {1, 2, 3, 4}
3交集
var a new Set([1, 2, 3]);
var b new Set([4, 3, 2]);
var intersect new Set([…a].filter(x b.has(x))); // {2, 3}
4差集
var a new Set([1, 2, 3]);
var b new Set([4, 3, 2]);
var difference new Set([…a].filter(x !b.has(x))); // {1}
7.2、Map
Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。
基本用法
const m new Map();
const o {p: ‘Hello World’};
m.set(o, ‘content’)
m.get(o) // “content”
m.has(o) // true
m.delete(o) // true
m.has(o) // false
Map中的key
key是字符串
var myMap new Map();
var keyString “a string”;
myMap.set(keyString, “和键’a string’关联的值”);
myMap.get(keyString); // “和键’a string’关联的值”
myMap.get(“a string”); // “和键’a string’关联的值”
// 因为 keyString ‘a string’
key是对象
ajax
1)ajax请求的原理/ 手写一个ajax请求 2)readyState 3)ajax异步与同步的区别 4)ajax传递中文用什么方法
[外链图片转存中…(img-r9nfexn9-1719211722806)]
[外链图片转存中…(img-xzvp885N-1719211722807)]