loveky / Blog

记录点滴
8 stars 2 forks source link

《ECMAScript 6 入门 第二版》读书会笔记 #8

Open loveky opened 7 years ago

kumamio commented 7 years ago

chapter1:

GET:

1. 使nodejs环境支持ES6语法,并进行调试。 step: 1)安装es-checker 2)安装babel,以及创建一个.babelrc的配置文件 ,安装babel-preset-es2015 3)在nodejs下测试es6代码,并查看es5转码。

2. 运行Webpack环境,并进行es6代码的调试 step: 1)clone买什么项目,安装webpack ,yarn, 及其依赖。 2)webpack.config.js 一些参数及路径 3) package.json 一些参数及命令 4) 转码入口jsx文件。

Q:

  1. babel src -d lib //编译整个src文件夹并输出到lib文件夹中 如果是编辑一个文件下的多个文件夹下的js怎么写?
  2. package.json 是不是npm 与yarn 共用一个的配置文件 ?

chapter2:

GET:

  1. 块级作用域
    const t = 3;
    if(true){
    const t = 5
    }
    t   // 3
  2. let 与 const 一样,不可重复声明
    
    let s = 3;
    let s = 5;  // Uncaught SyntaxError: Identifier 's' has already been declared at <anonymous>:1:1
3.块级作用域的出现,实际上使得获得广泛应用的立即执行匿名函数(IIFE)不再必要了。

(function () { var tmp = ...; ... }());

{ let tmp = ...; ... }

Onlyfor3ver commented 7 years ago

1、babel5版本默认包含各种转换插件,然而babel6.X相关转换插件需要自己下载。 babel-preset-es2015包含了所有插件,因此需要安装之后才能使用babel做到转换。但是babel只能转换ES6的语法,不能转换新的API,如Promise已经一些定义在全局上的方法例如:Object.assign。这时就得通过别的方法:1、babel-runtime 2、bable-polyfill 2、另外为了兼容性 要引入es5-shim和es5-sham。两者的区别:shim可以模拟ES5中可以被模拟的方法。sham是那些无法被模拟的方法,sham就尽力去模拟,只承诺不崩溃,不承诺是否有效。sham依赖于shim。https://github.com/es-shims/es5-shim 3、在IE8下,使用关键字或者保留字作为对象的属性值 例如 xxx.catch 会报错。 解决方法是 xxx['catch'] 或者引入 插件来处理 transform-es3-property-literals 和 transform-es3-member-expression-literals 4、let只在代码块中有效。不存在变量提升。相同作用域内,不允许重复声明。 5、ES5只有全局作用域和函数作用域,会导致 1、内层变量覆盖外层变量 2、用来计数的循环变量泄露为全局变量。 6、ES6的块级作用域允许声明函数只在使用大括号的情况下成立,如果未使用大括号,会报错 7、var 和 function 声明的全局变量 依旧是全局对象的属性。let const class 声明的全局变量 不属于全局对象的属性。

chapter3 1、function* fibs(){ var a = 0; var b = 1; while(true) { yield a; [a , b] = [b , a + b]; } } var [first,second,third,fourth,fifth,sixth] = fibs(); undefined first //0 second //1 third //1 fourth //2 fifth //3 sixth //5 a 0 b 1 a 1 b 1 a 1 b 2 a 2 b 3 a 3 b 5 a 5 b 7

2、在es6内部使用严格相等运算符,判断一个位置是否有值。所以一个数组成员不严格等于undefined,默认值是不会生效的。 3、对象的解构与数组 有一个重要的不同,数组的元素时按次序排列的,对象的属性没有次序,变量必须与属性同名。 4、 image

对象的解构赋值的内部机制,是先找到同名属性,然后再赋值给对应的变量。真正被赋值的是后者,而不是前者。

fannyCai commented 7 years ago

第二章 let和const命令

let let声明一个变量,只在let命令所在的代码块有效 暂时性死区:在代码块内使用let命令声明变量之前,该变量都是不可用的 let 不允许在相同作用域内重复声明同一个变量 可以使用let很方便实现块级作用域(IIFE)

const

const用来声明常量。一旦声明,其值就不能改变,一旦声明必须立即初始化,不能留到以后赋值 复合类型的变量,const只存储地址,内部值可以变化(Object.freeze() 冻结对象)

let,const,class 声明的全局变量不属于全局对象的属性

第三章 变量的解构赋值

解构:es6允许按照一定模式,从数组或对象中提取值,对变量进行赋值 模式匹配:等号两面的模式相同,左边的变量赋予对应的值

数组的解构

1、解构失败时,不成功的值等于undefined 2、允许不完全解构 3、解构赋值允许默认值存在,=右边必须是undefined 4、如果等号的右边不是数组,会报错

对象的解构

对象的解构赋值:先找到同名属性,然后再赋给对应的变量 对象的解构常用语对象方法的赋值 let { sin, cos } = Math;

数值和布尔值的解构会转为对象 const {toString :s} = true;

undefined 也会触发函数参数的默认值

解构的用途: 1、交换变量的值 2、从函数返回多个值 3、函数参数的定义 4、json数据提取 5、函数参数的默认值 6、遍历Map结构 7、输入模块的指定方法

maplehongye commented 7 years ago

Get: 1、ECMAScript的历史与混乱的版本命名(参考资料) 2、IT名词了解:交互式运行环境(REPL),babel和nodejs的REPL环境都支持es6

3、E C M A S c r i p t和 J a v a S c r i p t的关系是 ,前者是后者的规格 ,后者是前者的一种实现

4、E S 6明确规定 ,如果区块中存在 l e t和 c o n s t命令 ,则这个区块对这些命令声明的变量从一开始就形成封闭作用域 。只要在声明之前就使用这些变量 ,就会报错 。这在语法上称为 “暂时性死区 ” ( t e m p o r a l d e a d z o n e ,简称 T D Z ) 。暂时性死区的本质就是 ,只要一进入当前作用域 ,所要使用的变量就已存在 ,但是不可获取 ,只有等到声明变量的那一行代码出现 ,才可以获取和使用该变量 。

5、l e t不允许在相同作用域内重复声明同一个变量 。

6、需要注意的是 ,如果在严格模式下 ,函数只能在顶层作用域和函数内声明 ,其他情况 (比如 i f代码块 、循环代码块 )下的声明都会报错 。

7、对于复合类型的变量 ,变量名不指向数据 ,而是指向数据所在的地址 。 c o n s t命令只是保证变量名指向的地址不变 ,并不保证该地址的数据不变 ,所以将一个对象声明为常量必须非常小心 。

8、E S 5只有两种声明变量的方法 : v a r命令和 f u n c t i o n命令 。 E S 6除添加了 l e t和 c o n s t命令 ,后面章节还会提到另外两种声明变量的方法 : i m p o r t命令和 c l a s s命令 。所以 , E S 6一共有 6种声明变量的方法 。

9、const 用来 声明 常量。 一旦 声明, 其 值 就不 能改变。 对于 复合 类型 的 变量, 变量 名 不 指向 数据, 而是 指向 数据 所在 的 地址。 const 命令 只是 保证 变量 名 指向 的 地址 不变, 并不 保证 该 地址 的 数据 不变, 所以 将 一个 对象 声明 为 常量 必须 非常 小心。

hanyuxinting commented 7 years ago

4 字符串扩展

理解使用场景。 和为什么会出现这样的接口?

考虑一些不能被unicode识别的中文,需要用codePointAt()\fromCodePoint()\At()\遍历器接口; 关于字符串是否包含在另一个字符串中的方法:


var s = 'Hello world!';
s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true

var s = 'Hello world!';
s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false

重复字符串的方法:repeat 如果是整数,正的即为重复次数,负的报错。 如果是小数,忽略小数点及后数据。 -1-0为0 重复0次,就是不展示该串。 NaN为0; Infinity 则报错。 字符串?先字符串转化为数字。

使用方法: 'str'.repeat(2.7); //'strstr' 'str'.repeat('s'); // ''

字符串补齐: 数值补齐和日期补齐~~~着重,其他就是各种被字符串补齐

'1'.padStart(10, '0') // "0000000001"
'12'.padStart(10, '0') // "0000000012"
'123456'.padStart(10, '0') // "0000123456"
'12'.padStart(10, 'YYYY-MM-DD') // "YYYY-MM-12"
'09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"
'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'

'abc'.padStart(10, '0123456789')
// '0123456abc'

模板字符串-我喜欢。。

老:

$('#result').append(
'There are <b>' + basket.count + '</b> ' +
'items in your basket, ' +
'<em>' + basket.onSale +
'</em> are on sale!'
);

新:

$('#result').append(`
There are <b>${basket.count}</b> items
in your basket, <em>${basket.onSale}</em>
are on sale!
`);
//  普通字符串
`In JavaScript '\n' is a line-feed.`
//  多行字符串
`In JavaScript this is
not legal.`
console.log(`string text line 1
string text line 2`);
//  字符串中嵌入变量
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

当然这样就不可避免的出现行内的空格和行首行尾的空格,行尾行首可以用 trim 去掉~

$('#list').html(`
<ul>
<li>first</li>
<li>second</li>
</ul>
`.trim());

模板引用变量的方式,可以联想trimpath、vm的语法,类似~ 不仅可以引用变量,还可以进行运算,甚至可以调用函数~

var x = 1;
var y = 2;
`${x} + ${y} = ${x + y}`
// "1 + 2 = 3"

`${x} + ${y * 2} = ${x + y * 2}`
// "1 + 4 = 5"

var obj = {x: 1, y: 2};
`${obj.x + obj.y}`
// 3

function fn() {
return "Hello World";
}
`foo ${fn()} bar`
// foo Hello World bar

嵌套方式:


const tmpl = addrs => `
<table>
${addrs.map(addr => `
<tr><td>${addr.first}</td></tr>
<tr><td>${addr.last}</td></tr>
`).join('')}
</table>
`;

const data = [
{ first: '<Jane>', last: 'Bond' },
{ first: 'Lars', last: '<Croft>' },
];
console.log(tmpl(data));

Q: 如果大括号中的值不是字符串,将按照一般的规则转为字符串。比如,大括号中是一个对象,将默认调用对象的toString方法。??

数组的扩展

Array.from方法用于将两类对象转为真正的数组:类似数组的对象( array-like object )和可遍历( iterable )的对象(包括 ES6 新增的数据结构 Set 和 Map )。 类似数组的对象,本质特征只有一点,即必须有length属性。

任何有length属性的对象,都可以通过Array.from方法转为数组,而此 时扩展运算符就无法转换。

let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES5 的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6 的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

可以批量给素材改样式么。。

// NodeList 对象
let ps = document.querySelectorAll('p');
Array.from(ps).forEach(function (p) {
console.log(p);
});
// arguments 对象
function foo() {
var args = Array.from(arguments);
// ...
}
Array.from('hello')
// ['h', 'e', 'l', 'l', 'o']
let namesSet = new Set(['a', 'b'])
Array.from(namesSet) // ['a', 'b']

扩展运算符的功效: 扩展运算符背后调用的是遍历器接口(Symbol.iterator)

// arguments 对象
function foo() {
var args = [...arguments];
}
// NodeList 对象
[...document.querySelectorAll('div')]
[...'hello']
// ["h", "e", "l", "l", "o"]

Array.from({ length: 3 });
// [ undefined, undefined, undefined ]

替代方案:

const toArray = (() =>
Array.from ? Array.from : obj => [].slice.call(obj)
)();
Array.from(arrayLike, x => x * x);
//  等同于
Array.from(arrayLike).map(x => x * x);
Array.from([1, 2, 3], (x) => x * x)
// [1, 4, 9]

把一组值转化成数组

是弥补数组构造函数Array()的不足 Array.of基本上可以用来替代Array()或new Array()

Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1

Array.of() // []
Array.of(undefined) // [undefined]
Array.of(1) // [1]

typeof(Array.of(undefined)[0])
// "undefined"
function ArrayOf(){
return [].slice.call(arguments);
}

数组的copyWithin

Array.prototype.copyWithin(target, start = 0, end = this.length)

[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]

数组实例的find方法,用于找出第一个符合条件的数组成员。


[1, 4, -5, 10].find((n) => n < 0)
// -5

[1, 5, 10, 15].find(function(value, index, arr) {
return value > 9;
}) // 10

[1, 5, 10, 15].findIndex(function(value, index, arr) {
return value > 9;
}) //2

[NaN].indexOf(NaN)
// -1
[NaN].findIndex(y => Object.is(NaN, y))
// 0

 Object.is(NaN, NaN)
//true

fill

fill方法使用给定值,填充一个数组。

['a', 'b', 'c'].fill(7)
// [7, 7, 7]
new Array(3).fill(7)
// [7, 7, 7]

['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']

['a', 'b', 'c'].fill(7, 1)
//["a", 7, 7]

遍历数组

entries(),keys()和values() 可以 用for...of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。

for (let index of ['a', 'b'].keys()) {
console.log(index);
}
// 0
// 1

//其实并不支持目前的浏览器~~~
for (let elem of ['a', 'b'].values()) {
console.log(elem);
}
// 'a'
// 'b'
for (let [index, elem] of ['a', 'b'].entries()) {
console.log(index, elem);
}
// 0 "a"
// 1 "b"
let letter = ['a', 'b', 'c'];
let entries = letter.entries();
console.log(entries.next().value); // [0, 'a']
console.log(entries.next().value); // [1, 'b']
console.log(entries.next().value); // [2, 'c']

includes

Array.prototype.includes方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似。

[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
[1, 2, NaN].includes(NaN); // true
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true

indexOf方法有两个缺点,一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于 -1 ,表达起来不够直观。二是,它内 部使用严格相当运算符( === )进行判断,这会导致对NaN的误判。

[NaN].indexOf(NaN)
// -1

[NaN].includes(NaN)
// true
Onlyfor3ver commented 7 years ago

1、ES6为字符串提供了遍历器接口,使得字符串可以被 for 。。of循环遍历,该遍历器最大的优点是识别大于0xFFFF的码点 2、通过polyfill可以使用at()方法 该方法可以识别大于0xFFFF的字符 返回正确的字符。 3、includes() 返回布尔值 表示是否找到了参数字符串 startsWith() endsWith() 三种方法都有第二个参数 n endsWith的参数代表前n个字符查找 includes 和 startsWith代表第n个位置知道字符串结束 4、padStart用于头部补全,padEnd用于尾部补全。接受两个参数 第一个是用来指定字符串的最小长度 第二个参数是用来补全的字符串,省略第二个参数则用空格补全 image image 1、Array.from 用于将两类对象转为真正的数组:类似数组的对象(本质有一点,即必须有length属性,这种对象不能用扩展运算符来转换数组) 和 可遍历的对象 2、扩展运算符背后调用的是遍历器接口。因此扩展运算符可以将某些数据(nidelist)结构转为数组。 3、Array.from接受第二个参数,相当于数组的map方法,用于对数组的每个元素进行操作。将处理后的值返回给数组。 4、Array.of 总是返回参数值组成的数组,如果没有参数,就返回一个空数组 5、copyWith方法在当前数组内部,将指定位置的成员复制到其他位置,返回当前数组。 Array.prototype.copyWithin(target, start = 0, end = this.length) target必选 从该位置开始替换数组 start 从该位置读取数据 end 表示到该位置停止读数据 6、fill()方法使用给定值,填充一个数组。fill方法可以接受三个参数,第一个参数为填充值 第二个参数为填充的起始位置 第三个参数为结束为止 7、 entries()是对键值对的遍历 keys()是对键名的遍历 values()是对键值的遍历 8、Array.prototype.includes方法返回一个布尔值,表示某个数组是否包含给定的值。第二个参数表示搜索的起始位置,默认为0 9、map结构的has方法是用来查找键名 set结构的has方法是用来查找值。 10、 forEach filter every some 都会跳过空位
map会跳过空位 ,但是会保留值
join和toString会将空位视为undefined 而undefined和null会被处理成空字符串 Array.from 方法会将数组的空位转为undefined 扩展运算符会将量空位转为undefined copyWith会将空位一起拷贝 fill会将空位视为正常的数组位置 for of 会遍历空位
entries keys values find findIndex都会将空位处理成undefined

kumamio commented 7 years ago

Chapter 4:字符串的扩展 Q:

  1. var a = 5;
    var b = 10;
    tag`Hello ${ a + b } world ${ a * b }`;
    // 等同于
    tag(['Hello ', ' world ', ''], 15, 50);

Chapter 7:数组的扩展 G:

  1. Array.from
Array.from({length: 5}, (v, i) => i)

let ps = document.querySelectorAll('p');
Array.from(ps).forEach(function (p) {
console.log(p);
});

function foo() { var args = [...arguments]; }

  1. 扩展运算符(...)可用于iterator接口的对象转换为数组 。

  2. copyWithin 方法 [1, 2, 3, 4, 5].copyWithin(0, 3, 4) ['a', 'b', 'c'].fill(7, 1, 2) [1, 5, 10, 15].findIndex(function(value, index, arr) { return value > 9;}) // 2 [1, 4, -5, 10].find((n) => n < 0)
fannyCai commented 7 years ago

字符串的扩展

1.includes(),startsWith(),endWith() includes():返回布尔值,表示是否找到了参数字符串。 startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。 endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。 支持第二个参数,表示开始搜索的位置,endsWith它针对前n个字符

2、repeat方法返回一个新字符串,表示将原字符串重复n次

3、padStart().padEnd() padStart用于头部补全,padEnd用于尾部补全

4、模板字符串 string ${变量}

数组的扩展

1、Array.from() Array.from(arrayLike[, mapFn[, thisArg]])

2、Array.of():将一组数值转换为数组

3、copyWithin(),复制数组的一部分到同一数组中的另一个位置,并返回它,而不修改其大小,会修改原数组 Array.prototype.copyWithin(target, start = 0, end = this.length)

4、 find() 方法返回数组中满足提供的测试函数的第一个元素的值 findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。 [NaN].findIndex(y => Object.is(NaN, y))

5、fill()方法,使用给定值填充数组

6、数组实例的entries()、keys()、和values()方法,主要用来遍历数组,keys()是对键名的遍历,values()是对键值的遍历,entries()是对键值对的遍历

var arr = ["a", "b", "c"];
var iterator = arr.entries();
for (let e of iterator) {
    console.log(e);
}

7、Array.prototype.includes方法返回一个布尔值,表示某个数组是否包含给定的值 8、数组的空位 处理规则不同意,尽量避免空位

Onlyfor3ver commented 7 years ago

1、funciton m1({x = 0, y = 0} = {}) {return [x,y]} function m2({x , y} = {x:0 , y: 0}) {return [x,y]} m1 参数的默认值是空对象 但是指定了 解构的默认值 m2 函数的默认值是具体属性的对象 但是 没有设置解构的默认值 2、null无法触发默认值
3、设置了默认值以后,函数的length属性将返回没有指定默认值的参数个数。 如果设置了默认值得参数不是尾参数 ,那么length属性也不再计入后面的参数。 4、rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中。rest参数必须为最后一个参数。函数的length属性 不包括rest参数。 5、spread运算符是三个点 好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列。 6、如果将扩展运算符用于数组赋值,只能放到参数的最后一位,否则会报错。 const [aaa,...bba,cc]= [1,2,3,4] 7、箭头函数不能用作Generator函数。 8、箭头函数的this绑定定义时所在的作用域,普通函数的this指向运行时所在的作用域。 9、函数表达式中,es5中的name为空 es6中的名字为赋值的变量名 image

hanyuxinting commented 7 years ago

https://github.com/hanyuxinting/Blog/issues/13

fannyCai commented 7 years ago

函数的扩展

rest参数

function push(array,...items){
array.push(...items)
}
Math.max(...[14,3,7])

合并数组 [...arr1,...arr2] 解构赋值结合 const [first,...rest] = [1, 2, 3, 4, 5] 转化类数组的对象

var nodelist = document.querySelectorAll('div');
var array = [...nodelist]

箭头函数 1、函数体内的this对象就是定义是所在的对象 2、不可以试用arguments对象,可以用rest代替 3、不可以用当做构造函数,即不可以用new命令

Onlyfor3ver commented 7 years ago

1、ES5只能使用 var obj = {foo:true} es6可以 let a = 'a' let obj = {[a]:true} //属性简洁表示法 2、表达式还可以定义方法名 let obj = {['h' + 'ello'] () {return 'hi';} } obj.hello() //hi 3、属性名表达式与简洁表示法 不能同时使用 var foo = 'bar' ; var baz = {[foo]} 4、Object.is()用于判断严格相等 与 === 不一致的地方有两点 Object.is(+0,-0) false Object.is(NaN,Nan) true 5、Object.assign用于对象的合并,将源对象的所有可枚举属性,复制到目标对象。实行的是浅拷贝。 6、es5有三个操作会忽略enumerable为false的属性: for ... in 之遍历对象自身的和继承的可枚举属性 Object.assign() 返回对象自身的所有可枚举的属性的键名 JSON.stringify() 只串行化对象自身的可枚举的属性 Object.assign() 只拷贝对象自身的可枚举属性 for in 会返回继承的属性。 7、Object.entries 方返回一个数组,成员是参数对象自身的(不包含继承的)所有可遍历属性的键值对数组 8、Object.keys(obj) 返回一个数组 包括对象自身的所有可枚举属性 Object.getOwnPropertyNames(obj) 返回一个数组 包含对象自身的所有属性 不包含Symbol属性 但是包括不可枚举属性 Object.getOwnPropertySymbols(obj) 返回一个数组 包含对象自身的所有Symbol属性 Reflect.ownKeys(obj) 返回一个数组 包含对象自身的所有属性。 遍历次序规则: 首先遍历所有属性名为数值的属性,按照数字排序 其次遍历所有属性名为字符串的属性,按照生成时间排序 最后遍历所有属性名为Symbol值的属性,按照生成时间排序

fannyCai commented 7 years ago

对象的扩展

1、对象中允许只写属性名,不写属性值,属性值等于属性名代表的变量 2、 属性名表达式与简洁表示法不能同时使用,否则会报错 3、Object.is()用来比较两个值是否严格相等,与严格等(===)的行为基本一致,不同之处只有两个

4、Object.assign() 将源对象的所有的可枚举属性复制到目标对象 如果目标对象与源对象有同名属性,后面的属性会覆盖前面的属性

kumamio commented 7 years ago

1.ES6允许在对象之中, 只写属性名, 不写属性值。 这时, 属性值等于属性名所代表的变量。 2.( 1) for...in for...in循环遍历对象自身的和继承的可枚举属性( 不含Symbol属性) 。 ( 2) Object.keys(obj) Object.keys返回一个数组, 包括对象自身的( 不含继承的) 所有可枚举属性( 不含Symbol属性) 。 ( 3) Object.getOwnPropertyNames(obj) Object.getOwnPropertyNames返回一个数组, 包含对象自身的所有属性( 不含Symbol属性, 但是包括不可枚举属性) 。 ( 4) Object.getOwnPropertySymbols(obj) Object.getOwnPropertySymbols返回一个数组, 包含对象自身的所有Symbol属性。 ( 5) Reflect.ownKeys(obj) Reflect.ownKeys返回一个数组, 包含对象自身的所有属性, 不管是属性名是Symbol或字符串, 也不管是否可枚举。 3.Object.setPrototypeOf()

fannyCai commented 7 years ago

Set 和Map 数据结构

Set 类似数组,单成员的值是唯一的,没有重复的值 image

属性和方法

遍历操作

由于Set结构没有键名,只有键值,所有keys和values方法的行为完全一致

image 简洁去重 image

遍历中需要改变Set结构 ` let set3 = new Set([1, 2, 3]); set3 = new Set([...set3].map(val => val*2 ))

let set4 = new Set([1, 2, 3]); set4 = new Set(Array.from(set4,val => val*2)) ` WeakSet

不重复的值得集合,成员只能是对象,不能是其他类型的值,WeakSet的对象都是弱引用,成员无法引用,不可遍历

Map

Map 类似于对象,也是键值对的集合,“键” 的范围不限于字符串,可以是各种类型的值(包括对象)

Map 也可以接受一个数组作为参数,该数组的成员是一个个表示键值对的数值

image

如果对一个键多次赋值,后一次的值会覆盖前一次的值 如果读取一个未知的键,则返回undefined 只有对同一个对象的引用,Map结构才将其视为同一个键,同样的值的两个实例,在Map结构中视为两个键 如果Map 的键是一个简单类型的值(数字,字符串,布尔值),则只要两个值严格相等,Map就将其视为一个键,包括0,-0,NaN

实例的属性和操作方法

遍历操作

与其他类型数据结构的互相转换

var map = new Map([["name", "张三"], ["title", "Author"]])

1、转数组 [...map] image

Onlyfor3ver commented 7 years ago

1、set内部认为两个NaN是相等的 2、set实例的方法有: add(value) delete(value) 返回布尔值,表示删除是否成功 has(value) 返回一个布尔值,表示该值是否为set成员 clear()清空所有成员,没有返回值 3、set的遍历操作 keys() 返回键名的遍历器 values() 返回键值的遍历器 entries() 返回键值对的遍历器 forEach() 使用回调函数遍历每个成员 4、WeakSet结构与Set类似,区别在于 weakset的成员只能是对象,而不是其他类型的值 其次 weakset中的对象都是弱引用 即垃圾回收机制不考虑weakset对该对象的引用。也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象是否还在weakset中。 5、 Object是字符串-值 map结构是 值-值 6、map的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。map认为NaN相等,0 和 -0相等 7、size 返回map的成员总数 set(key,value) get(key) has(key) delete(key) clear() 8、map的遍历方法 keys values entries forEach

kumamio commented 7 years ago

Set 和 Map

1. set

G:

  1. add(value) , delete(value) , clear() , has()
  2. 遍历Set对象 1). for (let x of set) 2). set.forEach((value, key) => console.log(value * 2) ) 3), let arr = [...set]

    Q:

    1.对于dom的遍历

    function divs () {
    return [...document.querySelectorAll('div')] ;
    }

    [document.querySelectorAll('div')] 和 [...document.querySelectorAll('div')] 的区别

  3. var s = new Set([2,2,3,4])
    s.keys() == s.values()  //true

    key方法、 value方法、 entries方法返回的都是遍历器对象( 详见《 Iterator对象》 一章) 。 由于Set结构没有键名, 只有键值( 或者说键名和键值是同 一个值) , 所以key方法和value方法的行为完全一致。 3.[...set] 与 Array.from()差异

2. Map

G:

  1. 有delete, forEach, clear, has ,size, has ,keys方法 同Set对象, set 和 get 方法不同。

Q:

  1. Map 的键名可以是任何对象? 2.var myMap = new Map();

var keyObj = {}, keyFunc = function () {}, keyString = "a string";

// 添加键 myMap.set(keyString, "和键'a string'关联的值"); myMap.set(keyObj, "和键keyObj关联的值"); myMap.set(keyFunc, "和键keyFunc关联的值");

myMap.delete(keyString) //true myMap.values() // image

hanyuxinting commented 7 years ago

Get

有三类数据结构,自带Iterator神器。for of 默认会遍历。 数组、某些类似数组的对象,Set,Map。

let arr = ['a', 'b', 'c']; arr[Symbol.iterator]() // arr[Symbol.iterator]() image

image

image

字符串的遍历器接口 重载~~

image

遍历器-线性处理。部署遍历器接口就是部署一种线性转换。 对象不支持。但是它可以当做Map呀。

类似数组和非类似。。 image

Onlyfor3ver commented 7 years ago

1、 Iterator的作用有三个,一是为各种数据结构提供一个统一的简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是ES6创造了一种新的遍历命令for...of , Iterator接口主要供 for...of 。 2、 在ES6中,有三类数据结构原生具有Iterator接口:数组、某些类似数组的对象、Set和map结构。以上三类数据结构不需要自己写遍历器生成函数,for of会自动遍历他们,其他数据结构的Iterator接口,都需要自己在 Symbol.iterator属性上面部署,这样才会被for...of 循环遍历。 3、 解构赋值、扩展运算符、yield*、for of、Array.from、Map()、set()、weakMap()、weakSet()、Promise.all()、Promise.race() 等 默认调用Iterator 4、for in 有几个缺点: 1、数组的键名是数字 但是 for in循环是以字符串作为键名 '0' 2、for in 循环不仅遍历数字键名 还会遍历手动添加的其它键 包括原型链上的键 3、某些情况下 for in 循环会以任意顺序遍历键名

for in 不适合遍历数组 适合遍历对象。 5、 for of优点 1、有着不同于for in 一样的简洁语法 但是没有 for in的缺点 2、不同于forEach 他可以与break continue 和 return配合使用 3、提供了遍历所有数据结构的统一操作接口

Q:

对象部署遍历器接口不是很必要,因为这时对象实际上被当做map结构使用,那么能不能像类数组对象调用数组的Iterator方法一样,为对象调用例如map这样的数据结构的Iterator方法?

fannyCai commented 7 years ago

GET 1、JavaScript 中迭代器是一个对象,提供一个next()方法,返回序列中的下一项,这个方法返回包含done和value两个属性的对象 2、string,Array,TypedArray,Map 和Set都是内置迭代器,它们原型中都有一个Symbol.iterator 方法 3、for...in 只能获得对象的键名,不能直接获取键值,for...of 允许遍历获得键值

hanyuxinting commented 7 years ago

Get

next

next() 方法里的参数,是当做上一条yield返回值的。这个用来从外部不断注入数据。

image

V8引擎忽略第一次使用next的方法。。所以b的第一个next 和 c 的第一个next 返回结果一样~对y也没什么影响。

for...of

image

几种转化方法:

// 除了for...of循环以外,扩展运算符(...)、解构赋值和Array.from方法内部调用的,都是遍历器接口。这意味着,它们都可以将 Generator 函数返回的 Iterator 对象,作为参数

image

throw 方法

image

image

Onlyfor3ver commented 7 years ago

1、Generator函数是一个状态机,封装了多个内部状态。执行Generator函数会返回一个遍历器对象,依次遍历Generator内部的每一个状态/1、分段执行 2、可以控制阶段和每个阶段的返回值 3、可以知道是否执行到结尾。 2、yield本身没有返回值,或者总是返回undefined next方法可以带一个参数,该参数会被当做上一个yield的返回值。next的用途可以在Generator函数运行之后,继续向函数体内部注入值。 3、一旦Generator执行过程中抛出错误,且没有被内部捕获,就不会再执行下去,如果此后还调用next方法,将返回一个value属性等于undefined done属性等于true的对象。 4、如果Genetator函数内部有try finally块 那么return 方法会推迟到finally代码块执行完再执行。 5、yield*语句 用来在一个generator函数里面执行另外一个generator 6、 如果g函数的return语句后面依然有yield,则return后面的yield是白写 7、如果g函数没有yield和return 则第一次next就返回{ value:undefined,done:true} 8、如果g函数只有return 则第一次调用返回{ value:xxx,done:true} xxx为return的返回值,之后{ value:undefined,done:true} 9、同一个函数的不同遍历器互不干扰

fannyCai commented 7 years ago

Generator 函数返回遍历器对象,只有调用next方法才会遍历下一个内部状态。yield表达式 暂停表达式 1、遇到yidld表达式,就暂停执行后面的操作,并将跟在yield后面的那个表达式的值,作为返回的额对象的valued属性值 2、下一次调用next方法是,再继续往下执行,直到遇到下一个yield表达式 3、如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回对象的value属性值 4、如果该函数没有return语句,则返回的对象的value属性值为undefined 5、yield 表达式后面的表达式,只有当调用next方法,内部指针指向该语句是才会执行

Onlyfor3ver commented 7 years ago

1、Genetator函数返回的是一个状态机,因此没有this对象,想要调用this则需要动态绑定 2、Promise也有一些缺点,1.无法取消promise, 一旦创建就会立即执行。2. 如果不设置回到函数,Promise内部抛出的错误 不会反应到外部。 3. 当处于pending状态时,无法得知目前进展到哪一个阶段。 3、如果Promise状态变成了Resolved 在抛出错误是无效的 4、catch方法返回的还是一个promise对象,因此还可以接着调用then方法。 5、Promise.all 方法的参数可以不是数组,但必须具有Iterator接口,且返回的每个成员换都是Promise实例。 6、Promise.race() 只要有一个实例状态改变,则将该实例传递给回调函数继续执行。 7、立即resolve的Promise对象,是在本轮事件循环的结束时,而不是在下一轮事件循环的开始时。

fannyCai commented 7 years ago

Promise 三种状态

Promise实例生成以后,可以用then方法指定resolved状态和reject状态的回调函数,Promise新建后就会立即执行。而then方法中指定的回调函数,将在当前脚本所有同步任务执行完才会执行 image

API

Promise.prototype.then()

job1.then(job2).then(job3).catch(handleError); 每次调用then都会返回一个新创建的promise对象,而then内部只是返回的数据

Promise.prototype.catch()

Promise.all()

方法接受一个数组(或具有Iterator接口)作参数,数组中的对象(p1、p2、p3)均为promise实例,它的状态由这三个promise实例决定,这多个 promise 是同时开始、并行执行的

Promise.race()

方法同样接受一个数组(或具有Iterator接口)作参数。当p1, p2, p3中有一个实例的状态发生改变(变为fulfilled或rejected),p的状态就跟着改变。并把第一个改变状态的promise的返回值,传给p的回调函数

Q:

console.log(1);
new Promise(function (resolve, reject){
    reject();
    setTimeout(function (){
        resolve();            
    }, 0);
}).then(function(){
    console.log(2);
}, function(){
    console.log(3);
});
console.log(4);
kumamio commented 7 years ago
  1. promise的status image
  2. promise的链式调用 image
  3. Promise.all方法 image
Onlyfor3ver commented 7 years ago
var Thunk = function (fn) {
    return function (...args) {
        return function (callback) {
            return fn.call(this, ...args, callback);
        }
    }
}
function f(a, cb) {
    cb(a);
}
var ft = Thunk(f);
var log = console.log.bind(console);
ft(1)(log)

var Thunk = function (fn) {
    return function (...args) {
        return function (callback) {
            return fn.call(this, ...args, callback);
        }
    }
}

function f(a, b, c, cb) {
    cb(a, b, c);
}
var ft = Thunk(f);
var log = console.log.bind(console);
ft(1, 2, 3)(log)

var Thunk = function (fn) {
    return function (...args) {
        return function (callback) {
            return fn.call(this, ...args, callback);
        }
    }
}

function f(...a, cb) {
    cb(...a);
}
var ft = Thunk(f);
var log = console.log.bind(console);
ft(1,2,3,44,55)(log)

var Thunk = function (fn) {
    return function (...args) {
        return function (callback) {
            return fn.call(this, callback , ...args);
        }
    }
}

function f(cb, ...a) {
    cb(...a);
}
var ft = Thunk(f);
var log = console.log.bind(console);
ft(1,2,3,555)(log)

var Thunk = function (fn) {
    return function (...args) {
        return function (callback) {
            return fn.call(this, callback , ...args);
        }
    }
}

function f(cb, ...a) {
    for (var i of a) {
        cb(i);
    }
}
var ft = Thunk(f);
var log = console.log.bind(console);
ft(1,2,3,555)(log)