babel和webpack

babel

1、使用babel,需要安装babel/core @babel/cli
2、在package.json文件中配置


image.png

3、安装babel/preset-env


image.png

4、新建.babelrc文件配置
image.png

webpack

1、初始化项目

npm init

2、安装webpack需要的包


image.png

3、配置webpack
新建webpack.config.js文件配置
4、配置,运行


image.png

npm run webpack
5、babel和webpack一起使用
image.png

6、html-webpack-plugin
安装:


image.png

配置:
image.png

--------------------------------------------------------------promise------------------------------------------------
初识Promise
1、Promise 是异步操作的一种解决方案
Promise 一般用来解决层层嵌套的回调函数(回调地狱 callback hell)的问题
1.1、Promise的基本用法
实例化构造函数生成实例对象
Promise 的状态 :Promise 有 3 种状态,一开始是 pending(未完成),执行 resolve,变成 fulfilled(resolved),已成功
Promise 的状态一旦变化,就不会再改变了
resolve 和 reject 函数的参数

const p = new Promise((resolve, reject) => {
      reject(new Error('reason'));
    });
    p.then(
      data => {
        console.log('success', data);
      },
      err => {
        console.log('error', err);
      }
    );

    console.log(p);

2、 Promise的构造函数方法
Promise.resolve是成功状态 Promise 的一种简写形式.
//下面两种写法相同

new Promise(resolve => resolve('foo'));
Promise.resolve('foo');

参数
一般参数

    Promise.resolve('foo').then(data => {
        console.log(data);
      });

Promise对象:当 Promise.resolve() 接收的是 Promise 对象时,直接返回这个 Promise 对象,什么都不做

  const p1 = new Promise(resolve => {
        setTimeout(resolve, 1000, '我执行了');
        // setTimeout(() => {
        //   resolve('我执行了');
        // }, 1000);
      });
      Promise.resolve(p1).then(data => {
        console.log(data);
      });
      // 等价于
      p1.then(data => {
        console.log(data);
      });
      console.log(Promise.resolve(p1) === p1);

当 resolve 函数接收的是 Promise 对象时,后面的 then 会根据传递的 Promise 对象的状态变化决定执行哪一个回调

 new Promise(resolve => resolve(p1)).then(data => {
        console.log(data);
  });

具有then方法的对象

 const thenable = {
        then(resolve, reject) {
          console.log('then');
          resolve('data');
          // reject('reason');
        }
      };
      Promise.resolve(thenable).then(
        data => console.log(data),
        err => console.log(err)
      );
      console.log(Promise.resolve(thenable));

Promise.reject() 失败状态 Promise 的一种简写形式

new Promise((resolve, reject) => {
        reject('reason');
      });
      等价于
      Promise.reject('reason');

不管什么参数,都会原封不动地向后传递,作为后续方法的参数

 const p1 = new Promise(resolve => {
        setTimeout(resolve, 1000, '我执行了');
      });
      Promise.reject(p1).catch(err => console.log(err));

      new Promise((resolve, rejcet) => {
        resolve(123);
      })
        .then(data => {
          // return data;
          // return Promise.resolve(data);

          return Promise.reject('reason');
        })
        .then(data => {
          console.log(data);
        })
        .catch(err => console.log(err));

Promise.all()关注多个 Promise 对象的状态变化,传入多个 Promise 实例,包装成一个新的 Promise 实例返回

Promise.all() 的状态变化与所有传入的 Promise 实例对象状态有关

所有状态都变成 resolved,最终的状态才会变成 resolved
只要有一个变成 rejected,最终的状态就变成 rejected

 const delay = ms => {
        return new Promise(resolve => {
          setTimeout(resolve, ms);
        });
      };

      const p1 = delay(1000).then(() => {
        console.log('p1 完成了');

        // return 'p1';
        return Promise.reject('reason');
      });
      const p2 = delay(2000).then(() => {
        console.log('p2 完成了');

        return 'p2';
        // return Promise.reject('reason');
      });

const p = Promise.all([p1, p2]);
      p.then(
        data => {
          console.log(data);
        },
        err => {
          console.log(err);
        }
      );

Promise.race() Promise.race() 的状态取决于第一个完成的 Promise 实例对象,如果第一个完成的成功了,那最终的就成功;如果第一个完成的失败了,那最终的就失败

 const delay = ms => {
        return new Promise(resolve => {
          setTimeout(resolve, ms);
        });
      };
      const p1 = delay(1000).then(() => {
        console.log('p1 完成了');
        return 'p1';
      });
      const p2 = delay(2000).then(() => {
        console.log('p2 完成了');
        return Promise.reject('reason');
      });
  const racePromise = Promise.race([p1, p2]);
      racePromise.then(
        data => {
          console.log(data);
        },
        err => {
          console.log(err);
        }
      );

Promise.allSettled() 的状态与传入的Promise 状态无关,永远都是成功的,它只会忠实的记录下各个 Promise 的表现。

 const delay = ms => {
        return new Promise(resolve => {
          setTimeout(resolve, ms);
        });
      };
      const p1 = delay(1000).then(() => {
        console.log('p1 完成了');
        return 'p1';
      });
      const p2 = delay(2000).then(() => {
        console.log('p2 完成了');
        return Promise.reject('reason');
      });
 const allSettledPromise = Promise.allSettled([p1, p2]);
      allSettledPromise.then(data => {
        console.log('succ', data);
      });

3、Promise的实例方法
then方法
pending->fulfilled 时,执行 then 的第一个回调函数
pending->rejected 时,执行 then 的第二个回调函数
then 方法执行后默认是返回一个新的成功状态的Promise对象

 const p = new Promise((resolve, reject) => {
      reject();
    });
    p.then(
      () => {
        // console.log('success');
      },
      () => {
        console.log('err');
        // 在 then 的回调函数中,return 后面的东西,会用 Promise 包装一下
        return 123;
        // 等价于
        // return new Promise(resolve => {
        //   resolve(123);
        // });
      }
    )
      .then(
        data => {
          console.log('success2', data);
          return new Promise(resolve => {
            resolve(undefined);
          });
        },
        err => {
          console.log('err2', err);
        }
      )
      .then(
        data => {
          console.log('success3', data);
        },
        err => {
          console.log('err3', err);
        }
      );

catch方法,专门用来处理 rejected 状态,本质上是 then 的特例
catch() 可以捕获它前面的错误
一般总是建议,Promise 对象后面要跟 catch 方法,这样可以处理 Promise 内部发生的错误

new Promise((resolve, reject) => {
      reject('reason');
    })
      .then(data => {
        console.log(data);
      })
      .catch(err => {
        console.log(err);
        throw new Error('reason');
      })
      .then(data => {
        console.log(data);
      })
      .catch(err => {
        console.log(err);
      });

finally,本质上是 then() 的特例。
当 Promise 状态发生变化时,不论如何变化都会执行,不变化不执行

 new Promise((resolve, reject) => {
    // resolve(123);
    reject('reason');
     })
     .finally(data => {
  console.log(data);
   })
  .catch(err => {});

4、Promise的注意事项和应用
resolve 或 reject 函数执行后的代码
推荐在调用 resolve 或 reject 函数的时候加上 return,不再执行它们后面的代码
Promise.all/race/allSettled 的参数问题
参数如果不是 Promise 数组,会将不是 Promise 的数组元素转变成 Promise 对象
Promise.all/race/allSettled 的错误处理
错误既可以单独处理,也可以统一处理,一旦被处理,就不会在其他地方再处理一遍
异步加载图片

// 异步加载图片
      const loadImgAsync = url => {
        return new Promise((resolve, reject) => {
          const img = new Image();

          img.onload = () => {
            resolve(img);
          };

          img.onerror = () => {
            reject(new Error(`Could not load image at ${url}`));
          };

          img.src = url;
        });
      };

      const imgDOM = document.getElementById('img');
      loadImgAsync('https://2img.mukewang.com/5f057a6a0001f4f918720764.jpg')
        .then(img => {
          console.log(img.src);
          setTimeout(() => {
            imgDOM.src = img.src;
          }, 1000);
        })
        .catch(err => {
          console.log(err);
        });

----------------------------------------es6新增方法------------------------------------------------------
1、字符串的新增方法
includes 判断字符串中是否含有某些字符
(1)基本用法
console.log('abc'.includes('a')); // true
console.log('abc'.includes('ab')); //true
console.log('abc'.includes('bc')); //true
console.log('abc'.includes('ac')); // false
(2)参数
/*
第一个参数,必需,要查找的字符串。
第二个参数,可选,设置从那个位置开始查找,默认为 0
*/
console.log('abc'.includes('a')); //true
console.log('abc'.includes('a', 0)); //true
console.log('abc'.includes('a', 1)); // false
(3)应用 拼接url地址
let url = 'https://www.imooc.com/course/list?';
const addURLParam = (url, name, value) => {
url += url.includes('?') ? '&' : '?';

  url += `${name}=${value}`;

  return url;
};
url = addURLParam(url, 'c', 'fe');
console.log(url);
url = addURLParam(url, 'sort', 'pop');
console.log(url);

padStart和padEnd 补全字符串
(1)基本用法
console.log('x'.padStart(5, 'ab')); //ababx
console.log('x'.padEnd(5, 'ab')); //xabab
console.log('x'.padEnd(4, 'ab')); // xaba
(2)注意事项
原字符串的长度,等于或大于最大长度,不会消减原字符串,字符串补全不生效,返回原字符串
console.log('xxx'.padStart(2, 'ab')); // xxx
console.log('xxx'.padEnd(2, 'ab')); // xxx
用来补全的字符串与原字符串长度之和超过了最大长度,截去超出位数的补全字符串,原字符串不动
console.log('abc'.padStart(10, '0123456789')); //0123456abc
console.log('abc'.padEnd(10, '0123456789')); // abc0123456
如果省略第二个参数,默认使用空格补全长度
console.log('x'.padStart(4)); // x
console.log('x'.padEnd(4)); // x
(3)应用
padStart 显示日期
// 2020-10-10
console.log('10'.padStart(2, 0)); // 10
console.log('1'.padStart(2, 0)); // 01
trimStart和trimEnd方法,清除字符串的首或尾空格,中间的空格不会清除
(1)基本用法
const s = ' a b c ';
console.log(s.trimStart());
console.log(s.trimLeft());
console.log(s.trimEnd());
console.log(s.trimRight());
(2)应用: 提交数据时,去掉首尾空格

<input type="text" id="username" />
<input type="submit" value="提交" id="btn" />
<script>
const usernameInput = document.getElementById('username');
const btn = document.getElementById('btn');
btn.addEventListener(
  'click',
  () => {
    console.log(usernameInput.value);
    // 验证
    console.log(usernameInput.value.trim());
    if (usernameInput.value.trim() !== '') {
      // 可以提交
      console.log('可以提交');
    } else {
      // 不能提交
      console.log('不能提交');
    }
    // 手动提交
  },
  false
);
</script>

2、数组的新增方法
includes 判断数组中是否含有某个成员
(1)基本用法
console.log([1, 2, 3].includes('2')); // false
console.log([1, 2, 3].includes(2)); // true
(2)参数
/*
第一个参数,必须,需要查找的元素值。
第二个参数,可选,从该索引处开始查找 searchElement。如果为负值,则按升序从 array.length + fromIndex 的索引开始搜索。默认为 0。
*/
console.log([1, 2, 3].includes(2, 2)); // false
console.log([1, 2, 3].includes(2, -2)); //true
console.log([1, 2, 3].includes(3)); // false
(3)注意事项:基本遵循严格相等(===),但是对于 NaN 的判断与 === 不同,includes 认为 NaN === NaN
console.log(NaN === NaN); // false
console.log([1, 2, NaN].includes(NaN)); // true
(4)应用 数组去重

  const arr = [];
  for (const item of [1, 2, 1]) {
    if (!arr.includes(item)) {
      arr.push(item);
    }
  }
  console.log(arr);

Array.from 将其他数据类型转换成数组
(1)基本用法

console.log(Array.from('str')); // ["s", "t", "r"]
(2)可以通过 Array.from() 转换成数组

所有可遍历的 数组、字符串、Set、Map、NodeList、arguments

console.log(Array.from(new Set([1, 2, 1]))); //  [1, 2]
// 等价于
console.log([...new Set([1, 2, 1])]);
拥有 length 属性的任意对象
const obj = {
    '0': 'a',
    '1': 'b',
     name: 'Alex',
     length: 3
 };
console.log(Array.from(obj));

(3)参数

// 3.第二个参数 : 数组中每个元素要调用的函数
// 作用类似于数组的 map 方法,用来对每个元素进行处理,将处理后的值放入返回的数组

console.log(
[1, 2].map(value => {
  return value * 2;
})
);
console.log(Array.from('12', value => value * 2));
console.log(Array.from('12').map(value => value * 2));

// 4.第三个参数 映射函数(mapFunction)中的 this 对象

Array.from(
'12',
value => {
console.log(this);
},
document
);
Array.from(
'12',
function () {
console.log(this);
},
document
);

find和 findIndex方法

find():找到满足条件的一个立即返回值
findIndex():找到满足条件的一个,立即返回其索引
(1)参数
参数 描述
function(currentValue, index,arr) 必须。数组每个元素需要执行的函数。1、currentValue 必需,当前元素。2、index,可选,当前元素的索引。3、arr,可选。当前元素所属的数组对象
thisValue 可选。 传递给函数的值一般用 "this" 值。如果这个参数为空, "undefined" 会传递给 "this" 值
(2)代码示例

console.log(
       [1, 5, 10, 15].find((value, index, arr) => {
           // console.log(value, index, arr);
           console.log(this);
           return value > 9;
       }, document)
   );
   [1, 5, 10, 15].find(function(value, index, arr) {
       // console.log(value, index, arr);
       console.log(this);
       return value > 9;
   }, document);
   console.log(
       [1, 5, 10, 15].findIndex((value, index, arr) => {
           // console.log(value, index, arr);
           return value > 9;
       }, document)
   );

(3)应用 从获取到数据中筛选数据

const students = [
      {
        name: '张三',
        sex: '男',
        age: 16
      },
      {
        name: '李四',
        sex: '女',
        age: 22
      },
      {
        name: '王二麻子',
        sex: '男',
        age: 32
      }
    ];
    console.log(students.find(value => value.sex === '女'));
    console.log(students.findIndex(value => value.sex === '女'));

3、对象的新增方法
Object.assign 合并对象,相当于将后面的对象合并到第一个对象中
(1)基本使用
// Object.assign(目标对象, 源对象1,源对象2,...): 目标对象

    const apple = {
      color: '红色',
      shape: '圆形',
      taste: '甜'
    };
    const pen = {
      color: '黑色',
      shape: '圆柱形',
      use: '写字'
    };
    console.log(Object.assign(apple, pen));
    // console.log(Object.assign(apple, pen) === apple); true

(2)注意事项
基本数据类型作为源对象 与对象的展开类似,先转换成对象,再合并
console.log(Object.assign({}, undefined));
console.log(Object.assign({}, null));
console.log(Object.assign({}, 1));
console.log(Object.assign({}, true));
console.log(Object.assign({}, 'str'));
同名属性的替换 , 后面的直接覆盖前面的

const apple = {
    color: ['红色', '黄色'],
    shape: '圆形',
    taste: '甜'
  };
  const pen = {
    color: ['黑色', '银色'],
    shape: '圆柱形',
    use: '写字'
  };
  console.log(Object.assign({}, apple, pen));

(3)应用 合并默认参数和用户参数

    const logUser = userOptions => {
    const DEFAULTS = {
      username: 'ZhangSan',
      age: 0,
      sex: 'male'
    };

    const options = Object.assign({}, DEFAULTS, userOptions);
    // const options = Object.assign({}, DEFAULTS, undefined);
    console.log(options);
  };
  logUser();
  // logUser({});
  // logUser({ username: 'Alex' });

Object.keys 获取对象中属性名的集合
Object.value 获取对象中属性值值的集合
Object.entries 获取对象中属性和值的集合
(1)基本用户

const person = {
    name: 'Alex',
    age: 18
  };
  console.log(Object.keys(person));
  console.log(Object.values(person));
  console.log(Object.entries(person));

(2)与数组类似方法的区别
数组的 keys()、values()、entries() 等方法是实例方法,返回的都是 Iterator
对象的 Object.keys()、Object.values()、Object.entries() 等方法是构造函数方法,返回的是数组

const person = {
        name: 'Alex',
        age: 18
    };
    console.log([1, 2].keys());
    console.log([1, 2].values());
    console.log([1, 2].entries());
    console.log(person.keys);

(2)使用 for...of 循环遍历对象

  for (const key of Object.keys(person)) {
      console.log(key);
    }
    for (const value of Object.values(person)) {
      console.log(value);
    }
    for (const entries of Object.entries(person)) {
      console.log(entries);
    }

--------------------------------------------------------遍历器和for循环---------------------------------------
1、Iterator是什么
Iterator 是 ES6 引入的一种新的遍历机制,Iterator本质是一个指针对象,其中包含一个next方法,这个方法可以改变指针的指向,并且返回一个包含value和done的对象,value为当前所指向的成员的值,done表示是否遍历完成

可遍历数据原型继承了Symbol.iterator
const it = [1, 2]Symbol.iterator;
console.log(it);
可以调用Iterator的next方法,查看遍历的过程
const it = [1, 2]Symbol.iterator;
/*
value:当前属性的值
done:判断是否遍历结束 为 true 时则遍历结束
*/
console.log(it.next()); // {value: 1, done: false}
console.log(it.next()); // {value: 2, done: false}
console.log(it.next()); // {value: undefined, done: true}
console.log(it.next()); // {value: undefined, done: true}
2、Iterator解惑
为什么需要 Iterator 遍历器 :为了统一遍历的方式,在ES6推出了Iterator遍历机制
遍历数组:for 循环和 forEach 方法
遍历对象:for in 循环
如何更方便的使用 Iterator: 使用for...of方法遍历
3、for...of用法
for...of循环的本质就是将next方法遍历的过程封装,只遍历那些 done 为 false 时,对应的 value 值
// 使用next遍历过程

const arr = [1, 2, 3];
const it = arr[Symbol.iterator]();
let next = it.next();
while (!next.done) {
  console.log(next.value);
  next = it.next();
}
// 使用for...of直接就遍历了
for (const item of arr) {
  console.log(item);
}

4、for...of的使用
与break和continue关键字结合使用

const arr = [1, 2, 3];
for (const item of arr) {
  if (item === 2) {
    // break;
    continue;
  }
  console.log(item);
}

在 for...of 中取得数组的索引
keys() 得到的是索引的可遍历对象,可以遍历出索引值

const arr = [1, 2, 3];
for (const key of arr.keys()) {
  console.log(key);
}
```
values() 得到的是值的可遍历对象,可以遍历出值
```
const arr = [1, 2, 3];
for (const value of arr.values()) {
  console.log(value);
}
```
entries() 得到的是索引+值组成的数组的可遍历对象
const arr = [1, 2, 3];
for (const entries of arr.entries()) {
  console.log(entries);
}
```
5、原生可遍历和非原生可遍历对象
只要有 Symbol.iterator 方法,并且这个方法可以生成可遍历对象,就是可遍历的,可以使用 for...of 循环来统一遍历

原生可遍历对象
数组
字符串
Set
Map
arguments
NodeList
非原生可遍历对象
一般对象 var obj ={}
手动添加Iterator,然后使用for...of遍历
const person = { sex: 'male', age: 18 };
person[Symbol.iterator] = () => {
  let index = 0;
  return {
    next() {
      index++;

      if (index === 1) {
        return {
          value: person.age,
          done: false
        };
      } else if (index === 2) {
        return {
          value: person.sex,
          done: false
        };
      } else {
        return {
          done: true
        };
      }
    }
  };
};

for (const item of person) {
  console.log(item);
}
有length和数字索引的对象
// 有 length 和索引属性的对象
const obj = {
  '0': 'alex',
  '1': 'male',
  length: 2
};
// 第一种方法,直接设置iterator
obj[Symbol.iterator] = Array.prototype[Symbol.iterator];
// 第二种方法,手动添加iterator
obj[Symbol.iterator] = () => {
  let index = 0;
  return {
    next() {
      let value, done;
      if (index < obj.length) {
        value = obj[index];
        done = false;
      } else {
        value = undefined;
        done = true;
      }
      index++;
      return {
        value,
        done
      };
    }
  };
};
for (const item of obj) {
  console.log(item);
}
6、使用了Iterator的场合
所有的原生可遍历对象
数组的展开运算符
数组的解构赋值
Set 和 Map 的构造函数

-------------------------------------------set和map---------------------------------------------
1、什么是Set
set是一系列无序,没有重复值的集合

Set中不能有重复的成员
const s = new Set();
s.add(1);
s.add(2);
s.add(1);
console.log(s); //{1, 2}
Set 没有下标去标示每一个值,所以 Set 是无序的,也不能像数组那样通过下标去访问 Set 的成员
2、Set实例的方法和属性
方法
add 添加成员
delete 删除成员
clear 清除成员
has 判断是否包含某一个成员
forEach 遍历获取所有的成员
 const s = new Set();
   s.add(1).add(2).add(2);
 s.forEach(function (value, key, set) {
        // Set 中 value = key
        console.log(value, key, set === s);
        // console.log(this);
      }, document);
      console.log(s);
属性
size 获取所有的成员个数
3、Set构造函数的参数
数组、字符串、arguments、NodeList、Set 等都可以作为参数传递

<p>1</p>
    <p>2</p>
    <p>3</p>
    <script>
      // 1.数组
      const s = new Set([1, 2, 1]);
      console.log(s); // {1, 2}

      // 2.字符串、arguments、NodeList、Set 等
      console.log(new Set('hi')); //{"h", "i"}
      function func() {
        console.log(new Set(arguments));//{1, 2}
      }
      func(1, 2, 1);
      console.log(new Set(document.querySelectorAll('p'))); //{p, p, p}

      const s1 = new Set([1, 2, 1]);
      console.log(new Set(s1) === s1); // false
      console.log(s1); //{1, 2}
    </script>
4、Set注意事项
判断重复的方式
Set 对重复值的判断基本遵循严格相等(===)
但是对于 NaN 的判断与 === 不同,Set 中 NaN 等于 NaN

const s1 = new Set([1, 2, 1]); // {1,2}
const s2 = new Set([NaN, 2, NaN]); // {NaN, 2}
什么时候使用 Set
数组或字符串去重时
不需要通过下标访问,只需要遍历时
为了使用 Set 提供的方法和属性时(add delete clear has forEach size 等)
5、Set的应用
数组去重
const s = new Set([1, 2, 1]);
console.log(s); // {1,2}
字符串去重
const s = new Set('abbacbd');
console.log([...s].join(''));
console.log(s);
存放DOM元素,使用forEach方法遍历
 const s = new Set(document.querySelectorAll('p'));
 console.log(s);
  s.forEach(function (elem) {
        // console.log(elem);
        elem.style.color = 'red';
        elem.style.backgroundColor = 'yellow';
 });
6、认识 Map
Map 和对象都是键值对的集合

Map 和对象的区别
对象:一般使用字符串作为键名
Map:所有的数据类型都可以作为键名
const m = new Map();
m.set('name', 'alex');
m.set(true, 'true');
m.set({}, 'object');
m.set(new Set([1, 2]), 'set');
m.set(undefined, 'undefined');
console.log(m);
7、Map实例的方法和属性
方法
set 添加成员
get 获取成员
clear 清除成员
has 判断是否包含某一个成员
forEach 遍历获取所有的成员
delete 删除某一个成员
clear 清除所有的成员
属性
size 获取所有的成员个数
8、Map 构造函数的参数
只能传二维数组,而且必须体现出键和值
new Map(['name', 'alex', 'age', 18])
Set、Map 实例等,也必须体现出键和值
  // Set 中也必须体现出键和值
 const s = new Set([
    ['name', 'alex'],
    ['age', 18]
 ]);
console.log(new Map(s));
console.log(s);
// Map
// 复制了一个新的 Map
const m1 = new Map([
     ['name', 'alex'],
     ['age', 18]
]);
console.log(m1);
const m2 = new Map(m1);
 console.log(m2, m2 === m1);
9、Map的注意事项
判断重复的方式
Map 对重复值的判断基本遵循严格相等(===)但是对于 NaN 的判断与 === 不同,Set 中 NaN 等于 NaN
const s1 = new Set([1, 2, 1]); // {1,2}
const s2 = new Set([NaN, 2, NaN]); // {NaN, 2}
什么时候使用 Map
如果只是需要 key -> value 的结构,或者需要字符串以外的值做键,使用 Map 更合适
10、Map的应用
使用Map操作DOM对象,设置样式

<p>1</p>
    <p>2</p>
    <p>3</p>

    <script>
      const [p1, p2, p3] = document.querySelectorAll('p');
      // console.log(p1, p2, p3);
      // const m = new Map();
      // m.set(p1, 'red');
      // m.set(p2, 'green');
      // m.set(p3, 'blue');
      const m = new Map([
        [
          p1,
          {
            color: 'red',
            backgroundColor: 'yellow',
            fontSize: '40px'
          }
        ],
        [
          p2,
          {
            color: 'green',
            backgroundColor: 'pink',
            fontSize: '40px'
          }
        ],
        [
          p3,
          {
            color: 'blue',
            backgroundColor: 'orange',
            fontSize: '40px'
          }
        ]
      ]);

      m.forEach((propObj, elem) => {
        for (const p in propObj) {
          elem.style[p] = propObj[p];
        }
      });

      // m.forEach((color, elem) => {
      //   elem.style.color = color;
      // });
      console.log(m);
    </script>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容