关于forin、JSON格式、eval、ES6的新特性(进阶)

 一、forin

<body>

  <div></div>
  <div></div>
</body>
<script>

    const aDiv1 = document.querySelectorAll('div');
    const aDiv2 = document.getElementsByTagName('div');

    const obj = {
      name: 'mimi',
      age: 32
    }

    // 当key存在时,就继续循环.
    // in 是一个操作符.
    // key in obj 是一个表达式,返回布尔值.返回true表示obj有key属性,false表示没有.
    // 这里的key如果用let声明,是一个局部变量
    // 这里的key如果用var声明,就是一个全局变量.
    for (var key in obj) {
      // 属性名
      console.log(key);
      // 属性值
      console.log(obj[key]);
    }
    // key是全局变量,循环结束key是最后一个属性age
    console.log('key',key);

    // 如何知道某个对象能不能使用某个对象,或者属性.可以in检查.

    // aDiv1可以使用forEach
    // 'forEach' in aDiv1 => 判断aDiv1的原型链上有没有forEach这个方法或者属性.
    console.log('forEach' in aDiv1);// true
    // aDiv2不能使用forEach
    console.log('forEach' in aDiv2);// false

  </script>

二、forin循环数组 

<script>

    // 应用场景不多,所以不推荐用for in 循环数组。

    let arr = [1,2,3];
    // 给数组添加一个自定义属性
    arr.index = 4;

    let num = 0;

    // 用for in循环数组,会循环数组的自定义属性.而不是只循环元素.
    for (let i in arr) {
      console.log(arr[i]);
      num += arr[i];
    }

  </script>

三、json格式 

JSON.parse可以把json字符串转换为json对象

    json字符串有什么格式规定吗?

    1:第一个字符串只能是{或者[.最后一个字符,只能是}或者].

    2:属性名必须都是双引号.属性值如果是字符串也必须是双引号。

    3:最后一个属性不能加,

    4:不能有任何的注释.

 参数只能是json字符串.

    Unexpected token 小陈 in JSON at position 0 (参数的第一个字符"小陈"是错的)

    能写进parse方法的参数的字符串,必须是复合json格式的字符串

    const obj = JSON.parse('小陈');
    // 对的
    const obj = JSON.parse('[]');
    const obj = JSON.parse('{}');
    Uncaught SyntaxError: Unexpected token n in JSON at position 1
    const obj = JSON.parse('{name: 小陈}');
    SyntaxError: Unexpected token 小陈 in JSON at position 9
    const obj = JSON.parse('{"name": 小陈}');
    const obj = JSON.parse('{"name": "小陈"}');
    SyntaxError: Unexpected token } in JSON at position 14
    const obj = JSON.parse('{"name": "小陈",}');
    // 一定返回符合json格式的json字符串。
    let str = JSON.stringify({name: '小陈',});
    console.log(str);

四、eval 

<body>
  <input type="text">
</body>

eval => 把字符串当成js代码来运行.

eval返回的是它的参数的返回值.

    let obj = JSON.parse('{name: "小陈"}');
 // eval可以转换不符合json格式的字符串为对象.
    let obj = eval('({name: "小陈"})');
    'alert(100)'
    let num1 = eval('alert(20000)');
    let num2 = eval('Math.random()');
    // x没声明,直接访问x,会报错.
    eval('x');

    eval总数会把字符串当前js代码来运行,因此它不安全.
    如果这个字符串内包含了恶意代码,eval也会执行这些恶意代码。(xss攻击,脚本注入攻击)
    因此必须保证eval的内容是可信的.
    eval的参数不应该由用户输入提供.
    eval(oText.value);(不可取的).

五、ES6的新特性 

ES6新特性:

  •         let 和 const
  •        箭头函数
  •        块级作用域
  •        ··模板字符串
  •         rest参数和参数默认值
  •         function (...arguts, x = 100) {}

六、对象扩展 

     ES6的对象在属性和方法上有写法更简便的扩展.

    const obj = {
      name: name,
      age: age,
      show: function() {
        console.log('show');
      }
    }

    这里的写法和上面的obj是一个意思
    const oYm = { name, age };
    // 这里的写法和上面的obj是一个意思
    const oYm = { name, age };
    const oYm = {
      name, 
      age,
      // 方法可以不写:function
      show() {
        console.log('show');
      },
      // 动态属性名
      [x]: '女'
    };

    console.log(oYm.name);
    console.log(oYm.age);
    console.log(oYm[x]);

七、数值的扩展 

  •    parseFloat,parseInt是window的方法,实际上是不标准的方法.
  •     window的方法就是浏览器的方法.(BOM的方法).BOM是没有标准.
  •     BOM的所有方法如果业内都在使用,大家都把这些方法当成标准方法.
  •     window.parseFloat => 把字符串转换为小数
  •     window.parseInt => 把字符串转换为正数
  •     ES6就把一些BOM的常用方法变成标准之内的方法.
  •     例如数学上的parseFloat和parseInt,以及isNaN方法变成了Number类的标准方法.
    let num1 = Number.parseFloat('44.5');
    let num2 = Number.parseInt('44.8px');
    // isNaN也变成了Number的标准方法
    let flag = Number.isNaN(NaN);

    // 非标准方法
    window.isNaN('mimi');
    true
    window.isNaN('小陈');
    true
    window.isNaN({});
    true

    // 标准方法;
    Number.isNaN('mimi');
    false
    Number.isNaN('小陈');
    false
    Number.isNaN({});
    false

八、Math对象扩展 

    // 向下取整
    let num1 = Math.floor(4.9);// 4
    let num2 = Math.floor(-4.9);// -5
    // 直接把小数部分删掉
    let num3 = Math.trunc(4.9);// 4
    let num4 = Math.trunc(-4.9);// -4
    // flag返回1表示10是正数
    let flag = Math.sign(10);
    console.log(flag === 1);
    // flag是-1表示-10是负数.
    let flag = Math.sign(-10);
    console.log(flag === -1);

九、箭头函数 

 语法:

  •       () => {}
  •       res => res.x
  •       res => ({name: mimi})

箭头函数的简写:

  •     如果参数只有一个,可以省略形参的().

形参只有1个x,()可以省略掉.

  •     没有参数不能省略();
  •     多于1个参数不能省略();
  •     let fn = x => {console.log(x)};
  •     fn(1000);
  •     如果函数内只有一个return 语句,则return和{}都可以省略.

    // 函数内只有一个return语句
    let fun = () => {
      return 100
    }
    // 删掉{}和return.
    let fun = () => 100;

    // 形参是x,出参是100*x; (一眼看明白入参和出参各是什么)
    let fun = x => 100 * x;

    // 特别注意,函数对象的简写:

    let func = () => {
      return { name: '小陈' }
    }

    // 如果返回的是一个纯对象,简写后,应该有()包裹对象.
    let func = () => ({ name: '小陈' });

    // 这里的大括号是对象{}还是块级作用域的大括号?
    // 给参数添加一个小括号,就可以让eval知道,这是一个对象的{}
    let str = eval('({name: "小陈"})');

十、扩展运算符 

 ... => 扩展运算符 => 单目运算符.

    ...只能用在()中,[]中,以及{}中

    可以用于暂开数组,对象,甚至是字符串.

    ...的操作数除对象外,都是一些可以当成数组看待的数据.

    let arr = [1,2,3];
    let str = '我爱你';
    let obj = {name: '小陈', age: 32};

    console.log(arr[0], arr[1], arr[2]);
    console.log(str[0], str[1], str[2]);
    console.log(...arr);
    console.log(...str);
    // 如果展开的是一个纯对象,应该把...放到另一个{}内
    console.log(...obj);
    let oYm = {...obj}

    let num = [arr[0], arr[1], arr[2]];
    let num = [...arr];

    console.log(...100);

十一、解构赋值 

<script>

        let obj = {
            num:1,
            a:{
                num:2,
                a:{
                    num:3,
                    a:{
                        num:4,
                        a:{
                            num:5
                        }
                    }
                }
            }
        }

        let num = fn(obj);
        console.log(num); //15

        // 利用解构赋值,把参数o,解构成了两个变量
        // 这样可以直接通过num来代替o.num
        // 用a来代替o.a;
        function fn ({num, a}) {
            if (a !== undefined) {
                return num + fn(a)
            } else {
                return num
            }
        }

    </script>

十二、数组解构赋值 

    // 数组解构赋值

    let arr = [1, 2, 3];

    // 分别用3个变量存储了数组的3个元素
    let x = arr[0],
        y = arr[1],
        z = arr[2];
    // 以上写法可以改写成下面的写法。
    // 声明3个变量,分别获取数组的3个元素.
    let [x, y, z] = arr;
    console.log(x, y, z);

十三、对象解构赋值 

let obj = {
      exhusband: {
        name: '小邓'
      },
      arr: [
        {
          name: '小赵'
        }
      ]
    };

    let name = obj.exhusband.name;
    let { exhusband: {name} } = obj;
    console.log(name);// 小邓

    let {arr: [{ name }]} = obj;
    console.log(name); // 小赵

十四、解构赋值 

    let str = 'Hello';
    // 可以把字符串当成数组解构.
    let [x, y, z] = str;
    console.log(x, y, z);

    // 获取第一个div
    let [oDiv] = document.querySelectorAll('div');
    console.log(oDiv);

    // oDiv是undefined
    let {oDiv} = document.querySelectorAll('div');

    let obj = {name:'小陈'};
    // 报错
    let [name] = obj;

 =左边是写[]还是{}?

    = 左边写了[],浏览器就把=右边当成数组来解构.不能当数组处理的,会报错

    = 左边写了{},浏览器就把=右边当成对象来解构.除非右边是undefined或者null,其他情况都不会报错

    let arr = [1,2];
    // 数组也是对象,可以添加自定义属性.
    arr.x = 10;
    // 尝试解构[1,2]的自定义属性x.
    let {x} = arr;
    // undefined没有任何的x属性可以解构.
    // undefined和null不能当成对象来解构
    let {x} = undefined;
    // x也是undefined.(万物皆对象)
    // 基本类型的number,string,boolean都可以当成对象来解构
    let {x} = 100;
    let {y} = '你好';
    let {z} = true;
    // 尝试解构100的第一个元素.
    // 100不能当成数组解构
    let [x] = 100;

十五、iterator接口 

  • Array,Set,Map,String,nodeList (不包括纯对象)
  • 这些数据类型都可以当成数组来解构.
  • 能当成数组解构的数据类型是具有iterator接口的数据结构.
  •     js默认拥有iterator接口的数据类型是下面这些:
  •      Array => 数组
  •      Map => ES6新增的一种映射结构
  •      Set => ES6新增的一种不重复的数组结构
  •      String => 字符串
  •      TypedArray => 
  •      函数的 arguments 对象 => arguments
  •      NodeList 对象 => 标签数组
  •     注意: 纯对象没有iteraor接口.
  •     ...展开运算符,也可以展开所有具备iterator接口的数据类型.

十六、for of 

 for of => 循环具备iterator接口的数据结构

    for in => 循环对象

    let arr = [1,2,3];

    // val是数组的元素.for of 中没办法获取下标.
    // for (let val of arr) {
    //   console.log(val);
    // }

    // for (let val of 'Hello') {
    //   console.log(val);
    // }

    let aDiv = document.querySelectorAll('div');

    for (let el of aDiv) {
      // console.log(el);
      el.onclick = function() {
        console.log(el);
      }
    }

十七、数组去重 

<script>

    let arr = [1,1,2,2,3,3];
    // [1,2,3];

    // 算法 => 办法
    // 先声明一个空数组A.循环当前数组,检查A数组中,有没有当前循环的元素,没有就push进A,有就不push.
    // 面试题经常有这题.

    let newArr = [];

    for (let item of arr) {
      // 判断newArr中是否有当前的元素.
      if (!newArr.includes(item)) {
        newArr.push(item)
      }
    }

    

  </script>
<script>

    let arr = [1,1,2,2,3,3];
   
    // 去重的函数封装.
    let newArr = fn(arr);

    function fn(arr) {
      let newArr = [];
      for (let item of arr) {
        // 判断newArr中是否有当前的元素.
        if (!newArr.includes(item)) {
          newArr.push(item)
        }
      }
      return newArr
    }

  </script>

十八、Set结构 

<script>

    let arr = [1,1,2,2,3,3];
    // 利用Set结构来进行去重操作.
    let newArr = [...new Set(arr)];

    // Set => ES6新增的一种数据结构
    // js常用的数据结构: 数组,纯对象.
    // ES6新增了两种:Set,Map.
    // Set就是不重复的数组.
    // Map就是更"神经"的纯对象.

    // Set数据结构没有直接量的写法,只有构造的写法.

    // 参数必须是具备iterator接口的数据结构
    // let aS = new Set(1,2,3);

    // 可以接收数组作为参数.
    // Set的成员,绝对是不重复的.
    let aS = new Set([1,2,3,3]);
    // console.log(aS);
    // size相当于是数组的length.
    // console.log(aS.size);

    // 遍历访问Set的成员.
    for (let item of aS) {
      console.log(item);
    }
    // 添加一个成员
    aS.add(4);

    // 判断有没有指定元素.
    if (aS.has(5)) {
      alert('有5')
    } else {
      alert('没有5')
    }
    

  </script>

十九、Map 

<body>
  
  <div id='wrap'></div>
</body>
     const obj = {
      name: '小陈',
      age: 32,
      isMan: false
    };

    // const obj = {
    //   "name": '小陈',
    //   "age": 32,
    //   "isMan": false
    // };

    // 普通的纯对象的"键"的数据类型都是字符串."值"可以是任意数据类型.
    for (let key in obj) {
      console.log(typeof key)
    }
    const oDiv = document.getElementById('wrap');
     const data = {};

    // 这个name的数据类型必须是字符串.
     let name = 'name';

    // 这时,name的数据类型是对象.
     let name = oDiv;

     data.name = '空对象';
     data[name] = '空对象';
    const oDiv = document.getElementById('wrap');


    // 只有构造的写法.(相当于是一个空对象)
    let m = new Map();

    m.set('name', '小陈');
    m.set(oDiv, '这时一个div');

    // m.get('name') => 访问name映射的值.(name属性值)
    // m.get(oDiv) => 访问oDiv映射的值.(name属性值)

二十、数组缓存 

  •     随机取1-10的随机数10个.放入一个数组.要求不重复.
  •     可以用递归.但是性能不好.
  •     先创建一个1-10作为元素的数组.
  •     写一个10次循环,每次循环都随机从这个数组内获取一个元素.获取完成后删掉改元素.
  •     这样最终获取的10个数字就是不重复的.

let oBtn = document.querySelectorAll('button')[0];

    let arr = [1,2,3,4,5,6,7,8,9,10];

    // 不能这样缓存
    // let cloneArr = arr;

    oBtn.onclick = function() {

      // 缓存数组arr.
      // let cloneArr = [...arr];
      // let cloneArr = arr.concat([]);

      // 数组缓存的最优写法.
      let cloneArr = arr.slice();

       // 新数组,用于防止随机数.
      let newArr = [];

      for (let i = 0; i < 10; i++) {
        // 获取随机下标
        let index = Math.floor(Math.random() * cloneArr.length);
        // 把随机获取的元素放入新数组
        newArr.push(cloneArr[index]);
        // 把随机选中的元素删掉,防止下次再随到
        cloneArr.splice(index, 1);
      }

      console.log(newArr);
    }

二十一、参数是对象的解构 

<script>

    // 哪里可以用解构赋值?
    // 如果一个函数的参数是对象或者数组时,用得最多。

    let oYm = {
      name: '小陈',
      age: 32
    }
    
    // 函数调用时,形参会自动被实参赋值.
    // 如果我们的形参写成{}或者[]的形式,则程序会自动进行解构赋值.
    // obj = oYm
    // {name,age} = oYm
    function fn({name,age}) {
      console.log(name);
      console.log(age);
    }

    fn(oYm);

  </script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值