待深入:symbol,迭代器生成器,promise

部分参考https://blog.csdn.net/weixin_45495667/article/details/106967467

变量声明

let声明变量,const声明常量、

const声明常量(指向地址,数组用push等还是能改),值不能修改,一般使用大写(潜规则)。

var 和 let、const的区别

作用域

let 和 const 是块级作用域,仅在整个大括号内可见
var 只有全局作用域和函数作用域

变量提升

var 存在变量提升,未声明使用默认值undefined
let、const未声明会提示ReferenceError(不存在变量提升 )

console.log(a)        //undefined
var a = 1

console.log(a)
//Uncaught ReferenceError: a is not defined
let a = 1
重复声明

var 允许重复声明
let、const不允许在相同作用域重复声明

let a
let a
//Uncaught SyntaxError: Identifier 'a' has already been declared
全局对象属性

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

let b = 0
console.log(this.b)        //undefiend

变量解构赋值

数组解构
let [x, , y] = [1, 2, 3];
x // 1
y // 3


对象解构
let data = {
  id: 1,
  name: 'xiaoMing',
  age: 18
};
let { id, age } = data;
console.log(id, age);    //1, 18


字符串解构
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"

模板字符串

模板字符串是增强版的字符串,用反引号(`)标识,可以当作普通字符串使用,也可以用来定义多行字符。也可以结合${}实现在字符串中嵌入变量。

let a = `super
aaa`
let b = "star"
let c = `${a}${b}`    //相当于字符串a+b;
console.log(c)        
/*
super
aaastar
*/

可以在字符串内调用函数

function fn() {
  return "Hello World";
}

`foo ${fn()} bar`
// foo Hello World bar

箭头函数

=>

简化作用:
let fn = function(){xxx}
简化为:
let fn =() => {xxx}
tips

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。即继承上下文的this对象
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

tip:this 是静态的 this始终指向函数声明时所在作用域下的this的值

function是谁调用this就是谁,箭头函数是写在哪里this就是谁。

(3)箭头函数不能使用arguments,但1可以使用rest替代.

// 箭头函数
function id () {
    () => { console.log(this.id) }
}
// ES5普通函数
function id () {
    var _this = this;
    function () {
        console.log(_this.id) 
    }
}

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
function getname(){
console.log(this.naem);
}
let getname2 = () => {
conslole.log(this.name);
}

Window.name = '233';
const nico = {
name:'666'
}

直接调用
getname(); //233
getname2(); //233
方法调用
getname.call(nico); //666
getname2.call(nico; //23
//////rest替代arguments////////
let func = (...rest) => {
  console.log(rest)
  //[1,2,3]
}

func(1,2,3)

或者let func = (a,b,c,...rest)但rest一定要方最后
func(1,2,3,4,5,6,6,778,9)

遍历

for in循环遍历的是数组的键值(索引),而for of循环遍历的是数组的值。

for……of

语法:
for (variable of iterable) {
    //statements
}

/////
const array1 = ['a', 'b', 'c'];

for (const element of array1) {
  console.log(element);
}

// expected output: "a"
// expected output: "b"
// expected output: "c"
////////迭代Array
let iterable = [10, 20, 30];

for (let value of iterable) {
    value += 1;
    console.log(value);
}
// 11
// 21
// 31
//////////////迭代String
let iterable = "boo";

for (let value of iterable) {
  console.log(value);
}
// "b"
// "o"
// "o"
/////////////////迭代Map
let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]);

for (let entry of iterable) {
  console.log(entry);
}
// ["a", 1]
// ["b", 2]
// ["c", 3]

for (let [key, value] of iterable) {
  console.log(value);
}
// 1
// 2
// 3
////////////迭代 DOM 集合
//注意:这只能在实现了NodeList.prototype[Symbol.iterator]的平台上运行
let articleParagraphs = document.querySelectorAll("article > p");

for (let paragraph of articleParagraphs) {
  paragraph.classList.add("read");
}

for……in

for/in 语句用于循环对象属性。

循环中的代码每执行一次,就会对数组的元素或者对象的属性进行一次操作。

for (var in object) {
 执行的代码块
}

Promise


        const btn = document.getElementsByTagName('button')[0];
        btn.addEventListener('click',function(){

            const p = new Promise((resolve,reject) => {
                setTimeout(() => {
                    let n = Math.floor((Math.random()*100)+1);
                    if(n>30) 
                    {resolve();}
                    else
                    {reject();}
                }, 500);
            });  

            p.then(function(){
               alert('no');
            },function(){
                alert('yes!');
            })

        });


async-await

扩展运算符

【…】扩展运算符能将【数组】转化为逗号分隔的【参数序列】

应用场景

复制对象
let a = [11, 12, 13]
let b = a 
let c = [...a]
a.push(14)
console.log(b)        //[11, 12, 13, 14]
console.log(c)        //[11, 12, 13]
P.S. 只能针对一维数组
const obj = {a:{b:1}}
const {...x) = obj
obj.a.b = 2
console.log(b)    //{a:{b:2}}
合并对象
let a = {...obj1, ...obj2}
P.S. 后面的属性会覆盖前面同名属性
let obj1 = {a:1, b:2}
let obj2 = {...obj1, ...{a:2, b:4}}
console.log(obj2)        //{a:2, b:4}
变量解构(以及将伪数组转化为真数组)
const [first, ...last] = [1, 2, 3]
console.log(last)        //[2, 3]
/////////////////////
const divs =document.querySelectorALL('div');       //获得伪数组
const divArr = [...divs];             //伪转真
console.log(divArr);   //此时已经变成了真数组
扩展函数参数
function show(...a){
    console.log(a)        //[11, 12, 13]
}
show(11, 12, 13)

object.assign()

Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。它将返回目标对象。

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };

const returnedTarget = Object.assign(target, source);

console.log(target);
// expected output: Object { a: 1, b: 4, c: 5 }

console.log(returnedTarget);
// expected output: Object { a: 1, b: 4, c: 5 }

语法
Object.assign(target, source1,sur2,...)

参数

target

目标对象。

sources

源对象。

返回值

目标对象。

描述

如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性。

set和map数据结构

set

Set对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。

let mySet = new Set();

mySet.add(1); // Set [ 1 ]
mySet.add(5); // Set [ 1, 5 ]
mySet.add(5); // Set [ 1, 5 ]
mySet.add("some text"); // Set [ 1, 5, "some text" ]
let o = {a: 1, b: 2};
mySet.add(o);

mySet.add({a: 1, b: 2}); // o 指向的是不同的对象,所以没问题

mySet.has(1); // true
mySet.has(3); // false
mySet.has(5);              // true
mySet.has(Math.sqrt(25));  // true
mySet.has("Some Text".toLowerCase()); // true
mySet.has(o); // true

mySet.size; // 5

mySet.delete(5);  // true,  从set中移除5
mySet.has(5);     // false, 5已经被移除

mySet.size; // 4, 刚刚移除一个值

console.log(mySet);
// logs Set(4) [ 1, "some text", {…}, {…} ] in Firefox
// logs Set(4) { 1, "some text", {…}, {…} } in Chrome

map

Map对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者原始值)都可以作为一个键或一个值。

一个Map对象在迭代时会根据对象中元素的插入顺序来进行 — 一个 for…of 循环在每次迭代后会返回一个形式为[key,value]的数组。

Map.length:属性 length 的值为 0 。
想要计算一个Map 中的条目数量, 使用 [Map.prototype.size]

let myMap = new Map();

let keyObj = {};
let keyFunc = function() {};
let keyString = 'a string';

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

myMap.size; // 3

// 读取值
myMap.get(keyString);    // "和键'a string'关联的值"
myMap.get(keyObj);       // "和键keyObj关联的值"
myMap.get(keyFunc);      // "和键keyFunc关联的值"

myMap.get('a string');   // "和键'a string'关联的值"
                         // 因为keyString === 'a string'
myMap.get({});           // undefined, 因为keyObj !== {}
myMap.get(function() {}); // undefined, 因为keyFunc !== function () {}

Symbol

Symbol 值通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

特点:

1.Symbol值唯一,用来解决命名冲突的问题。

2.Symbol值不能与其他数据进行运算。

3.Symbol定义的对象属性不能使用for……in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名、

tips:Symbol.for()与Symbol()这两种写法,都会生成新的Symbol,区别是前者会被登记在全局环境中提供搜索,后者不会。

// 没有参数的情况
let s1 = Symbol();
typeof s1        // "symbol"
let s2 = Symbol();

s1 === s2         // false

// 有参数的情况
let s1 = Symbol('foo');
let s2 = Symbol('foo');

s1 === s2         // false
//Symbol.fot
let s1 = Symbol.fot('nico');
let s2 = Symbol.for('nico');
s1 === s2 //true

迭代器

生成器


菜菜子新人