this与ES6

99 阅读12分钟

改变this指向

  • this的指向:
    • this 的指向只跟函数的调用有关, 跟函数的书写没关系
  • 手动更改函数内部 this 指向的方法
  1. call
  • 语法: 函数.call(将函数内的this指向什么, 传递给函数的参数1, 传递给函数的参数2...)
  • 将方法附加在函数后调用, 可以忽略函数本身的this, 并且修改为你传递进去的第一个参数
  1. apply
  • 语法: 函数.apply(将函数内的this指向什么, [传递给函数的参数1, 传递给函数的参数2...])
  • 该方法和第一个方法类似, 也是附加在函数后调用, 可以忽略桉树本身的this, 并且修改为你传递进去的第一个参数
  1. bind
  • 该方法和前两个类似, 也是附加在函数后调用, 可以忽略函数本身的this, 并且修改为你传递进去的第一个参数
  • 但是和 call/apply 有一点完全不同, 就是 bind 使用之后, 不会立即调用原本的函数会返回一个功能与原本函数相同但是修改了 this 指向的函数
        var obj = {
            name: 'QF001',
            age: 18,
        }
        function fn(a, b) {
            console.log(this, a, b);
        }
        fn()
        //window undefined undefined
        fn(100,200) 
        window 100 200       
  1. 函数.call(修改this的指向)
fn.call(obj, 10, 20)
//{name: 'QF001', age: 18} 10 20
  1. 函数.apply(修改this的指向,[传递给函数的参数1,传递给函数的参数1])
fn.apply(obj, [10, 20])
//{name: 'QF001', age: 18} 10 20
  1. 函数.bind(修改this的指向)
        fn.bind(obj);
        // 不会立即调用
        var res = fn.bind(obj)
        console.log(res);
        /* fn(a, b) {
            console.log(this, a, b);
        } */
        // 打印出一个新的函数,不过内容思原来的
        res(100,200)
        // {name: 'QF001', age: 18} 100 200

ES5 和 ES6

  • ES5 和ES6 是 ECMAscript的某个版本

  • let / const 与 var 的区别

    1. var 会进行预解析
      • let 与const 不会进行预解析
//    1.预解析(变量提升)
        console.log(a)
        undefined
        var a = 100;
        console.log(a); // 100  
        在定义之前使用这个变量  不报错, 返回 undefined


        console.log(b); 
        // Uncaught ReferenceError: Cannot access 'b' before initialization
        // 报错  不能再定义之前使用这个变量(暂时性死区)
        let b = 200;
        console.log(b); 



        console.log(num);
        // // Uncaught ReferenceError: Cannot access 'b' before initialization
        // // 报错  不能再定义之前使用这个变量(暂时性死区)
        const num = 100;
        console.log(num);// 100
2. var 可以声明两个重名的变量
   * letconst   不能定义重名变量
// 2. 重复变量名
        var n1 = 100;
        var n1 = 200;
        console.log(n1);//200


        let n2 = 100;
        let n2 = 200;
        Uncaught SyntaxError: Identifier 'n2' has already been declared 


        const n2 = 100;
        const n2 = 200;
        // Uncaught SyntaxError: Identifier 'n2' has already been declared 
        // 报错
3. var没有块级作用域
   * letconst 有块级作用域
// 3.块级作用域
        // 定义: 任何一个代码段的{}都会限制该变量的使用范围
        if (true) {
            var num = 200;
            console.log(num);//200
        }
         console.log(num);//200
         var 定义的变量只有函数决定作用域
        在自己作用域里面找,有则打印,没有则打印undefined


        if (true) {
            let num1 = 200;
            console.log(num1);//200
            // let 定义的变量   只能在if 的  {} 内使用  
        }
        console.log(num1);
        Uncaught ReferenceError: num1 is not defined

        if (true){
           const  num2 =300;
           console.log(num2);//300
        // const 定义的变量   只能在if 的  {} 内使用  

        }
        console.log(num2);
        // Uncaught ReferenceError: num1 is not defined
        // 报错
  • let 与const 的区别
    1. let 可以定义变量的时候 不进行赋值
// 1. let 可以定义变量的时候 不进行赋值
         let num;
         console.log(num); //undefined
         num = 100;
         console.log(num);//100
  1. const 在定义的时候必须赋值
         const num;
        //   const  声明时  必须赋值
         Uncaught SyntaxError: Missing initializer in const declaration
        // const 在定义的时候必须赋值    因为const 定义时是常量
         console.log(num); //undefined
         num = 100;
         console.log(num);//100
  1. let 定义的变量可以修改
        let num = 400;
        console.log(num); //400
        num = 200;
        console.log(num); //200

  1. const 定义的常量一经赋值不能再修改
 // const num = 400;
        // console.log(num); //400
        // num = 200;
        // console.log(num); 
        // ES5和ES6.html:131 Uncaught TypeError: Assignment to constant variable.
        // 报错
        // const 定义的变量不能修改


//   实例
        const obj = {
            name: '张三',
            age: 18,
        };
        // obj.name = 'test'
        obj = {}    
        console.log(obj);
        // 报错      

箭头函数

  • 在ES6 中对 “函数表达式”的一种简写
  • 函数表达式 又叫做 匿名函数
    • 不需要单独定义的函数
    • 直接使用的位置
  • 在之前的函数里面 省略掉function 在() 和{}之间一个箭头
const fn = () => { }
setInterval(() => { })
setTimeout(() => { })
 xxx.forEach(() => { });
// 实例
        const fn1 = function () {
            console.log('我是fn1的函数');
            //我是fn1的函数
        }
        fn1();

        const fn2 = () => {
            console.log('我是fn2的箭头函数');
            //我是fn2的箭头函数
        }
        fn2();
  • 箭头函数的特殊时刻
  1. 箭头函数某些时候可以省略()
    • 当形参只有一个的时候 可以不写 ()
      注意: 必须只有一个形参的时候可以省略, 没有形参或者有多个形参, 必须写小括号
// 1.箭头函数某些时候可以省略()
         const  fn3 = =>{
            // 报错
            // Uncaught SyntaxError: Unexpected token '=>' 
            console.log('我没有参数');
            // 我没有参数
         }
         fn3();


        const fn4 = a => {
            console.log('我有一个形参:' + a);
            //我有一个形参:100
        }
        fn4(100);

        const fn5 = a, b => {
        // 报错
        // Uncaught SyntaxError: Unexpected token '=>'
            console.log('我有两个形参:', a, b);
        }
        fn5(100, 200);
  1. 箭头函数某写时候可以省略{}
    • 当你的代码只有一行的时候,可以不写{}并且自带return
    • 并且会自动把这一句话的结果当作函数的返回值
 //   2.箭头函数某写时候可以省略{}
        const fn1 = (a,b)=> a + b ;
        // 2.1 如果箭头函数需要执行的代码只有一行, 可以省略 大括号, 并且自带 return
        console.log(fn1(100,200));//300

  1. 箭头函数没有arguments
//  3.箭头函数没有arguments

        // const getfn = function (){
        //     console.log(arguments);
        // }
        // getfn(100,200,300);
        //[100,200,300,...]

        // const getfn1 = function () {
        //     console.log(arguments);
        // }
        // getfn1(100,200,300);
        //得到一个数组 并且有100,200 300 
// 能够拿到所有的传递进来的实参, 但是这种写法了解即可, 不推荐

        // const fn2 = ()=>{
        //     console.log(arguments);
        //报错  当前函数是箭头函数, 所以不能使用
        //     //Uncaught ReferenceError: arguments is not defined
        // }
        // fn2(100,200,300);
  1. 箭头函数内没有 this
    • 箭头函数内的this,就是外部作用域的this
    • 即:箭头函数没有 this, 箭头函数的 this 是上下文的 this (你的箭头函数写在哪里 this 就决定了)
      注意:我们在判断箭头函数的 this 是什么的时候, 可以从打印的这一行向上一行看但是因为上一行是在 对象 obj 的内部, 所以这个位置是不能书写 JS 代码的所以继续到 对象的上一行去看 this, 那就到了全局

箭头函数内部没有 this :
我们在判断箭头函数的 this 是什么的时候, 可以从打印的这一行向上一行看 但是因为上一行是在 对象 obj 的内部, 所以这个位置是不能书写 JS 代码的 所以继续到 对象的上一行去看 this, 那就到了全局, 所以这地方的 this fn1 箭头函数内部的 this

参数的默认值

  • 参数的默认值 (以前就讲过, 只不过参数的默认值是 ES6 新增的)
  • 其实就是对原本的普通函数写法上一个优化
    注意点: 箭头函数的参数如果需要使用默认值, 那么不管有多少个形参, 都必须书写小括号
function fn(a = 100, b = 200) {
            // 声明两个形参
            // 其中a设置默认值为 100
            // 其中b 设置默认值为200

            console.log('a:', a);
            console.log('b:', b);
            
        }
        // 两个实参都没有传递,都会只用默认值
        fn();   //a: 100   b: 200
        
        // 给 a 传递 实参2  b 不传递的实参
        fn(2);  // a: 2  b: 200


        // 给 a 传递实参10  b 传递实参20
        fn(10,20); // a: 10 b: 20

ES6 的展开运算符(扩展运算符)

  • 作用 : 展开数组的[]或者 展开对象的{}
    • 作用1: 常见的合并数; 将一个数组展开
    • 作用2: 给函数传递参数
    1. 展开数组
        console.log(100, 200, 300, 400,);
        //  100 200 300 400

        var  arr =[100,200,300,400];
        console.log(arr);
        //  [100, 200, 300, 400]
        console.log(...arr);
        100 200 300 400
        相当于 将数组去掉  []  即 console.log(100, 200, 300, 400,);

        作用1 :  常见的合并数组

        var arr1 = [11];
        var arr2 = [22];
        var arr3 = [33,44,55];

        //需求 :将所有数组的数据合并在一起

        var arr4 = [...arr1,...arr2,...arr3];
        // 注意 之间用 , 相连
        console.log(arr4);
         [11, 22, 33, 44, 55]


        var arr = [12, 15, 7, 8, 16, 20, 4];
        // 需求  求数组里的最大值
        // var max = Math.max(12, 15, 7, 8, 16, 20, 4)
        // var max = Math.max(arr);
        var max = Math.max(...arr)
        console.log(max); //20
        NaN  因为这里不认识数组  只能拿到NaN
        20  


        var arr1 = [1, 2, 3, 4]
        console.log(arr1);  //[1, 2, 3, 4]  新数组
        console.log(...arr1); //1 2 3 4   展开数组
        console.log([...arr1]);//[1, 2, 3, 4]  新数组
  1. 展开对象
var obj = { name: "张三", age: 18 };
        console.log(obj);// {name: '张三', age: 18}
        console.log(...obj);
        Uncaught TypeError: Spread syntax requires ...iterable[Symbol.iterator] to be a function
        报错  js不允许

        作用1: 复制对象
        注意:展开书写的顺序问题   在有相同成员的时候
        var obj1 = {
            sex: '男',
            name: 'jeck',
            ...obj,
        };
        console.log(obj1);
        {sex: '男', name: '张三', age: 18}



        var obj2 = {
            sex: '男',
            ...obj,
            name: 'jeck',
        };
        console.log(obj2);
         {sex: '男', name: 'jeck', age: 18} 
  1. 函数传参
var arr = [100, 200, 300];
        const fn = (a, b, c) => console.log(a,ba,c);


        // fn(arr[0],arr[1],arr[2])
        fn(...arr)

ES6中的解构赋值

  • 快速从 “对象” 或 “数组” 中获取 “成员” (在开发中很常用,简单方便快捷)
  • 解构赋值 分为 两种
    1. 数组的解构赋值
    2. 对象的解构赋值
  • 数组的解构赋值
    • 快速从数组中获取数据
    • 注意结构数组用 []
    • 按照索引进行匹配
  1. 对象的解构赋值
  • 快速从对象中获取数据
  • 注意结构数组用 {}
  • 按照 键值对 进行匹配
// 1.1以前
        let arr = [100, 200, 300,];
        let a = arr[0]
        let b = arr[1]
        console.log(a, b);
        //100 200


        //  1.2 现在
        arr = ['hello', 'world']
        let [a, b] = arr
        let [a,b] =['hello','world'];
        // // 此时获取的 a 为 arr[0]  b 为 arr[1]
        console.log(a);//hello
        console.log(b);// world

        // 2.对象的解构赋值
        // 快速从对象中获取数据


        // 1.1 以前

        var obj = {
            name: '张三',
            age: 18,
        }

        let name = obj.name
        console.log(name); //张三
        let age = obj.age
        console.log(age);//18

        // 1.2现在

        var obj = {
            name: '张三',
            age: 18,
        }
        let { name, age, a } = obj;
        // // 定义一个叫做 name 的变量, 获取的是 obj  内一个叫做 name 的成员的值 
        console.log(name);//张三  // var name = obj.name
        console.log(age);//18     // var age = obj.age
        console.log(a); //undefined  //  var a = obj.a

        /**
         *  前边的 {} 表明是解构赋值, 我需要从赋值号后边的 对象 obj(必须是对象)中
         *  拿到 age 和 name 属性
        */

        // 定义一个叫做 a 的变量, 获取的是 obj  内一个叫做 a 的成员的值  
        // 定义一个不一样的变量名
        var { a } = obj;   // var a = obj.a
        console.log(a);//undefined



        // 其实可以起一个别名
        // 定义一个叫做a 的变量 , 获取的是obj  内一个 叫做 age 的成员的值
        var { age: a } = obj   //  var a = obj.age
        console.log(a);//18    

模板字符串

  • ES6中 新增的定义字符串的方式
  • ES5 的时候字符串只能是 '' "" 包裹的内容
  • 弊端: 字符串内不能换行, 拼接变量的时候不方便
  • ES6 的模板字符串可以使用 `` 包裹, 内部如果需要添加变量, 可以书写一个 ${变量}
以前:
           var str = ''
           var str1 = ''
        现在:
           var str2 = `内容`
            
           区别: 
           1.可以换行书写 
           2.可以在字符串内解析变量
           => 当你需要解析变量的时候,直接书写${你要解析的变量}
        */

        var str1 = '1
        23'
        // 换行后打印会报错
        // Uncaught SyntaxError: Invalid or unexpected token
        var str1 = '1 23'
        var str2 = '1 23'
        /* var str3 = `1
         23`
        */
        //  ``   打印时会保留原样的换行
        console.log(str1);// 1 23
        console.log(str2);// 1 23
        console.log(str3);// 1 23
        console.log(str2 === str1);  // true
        console.log(str3 === str1);  // false 


        var age = 18;
        var s1 = `我今年18岁`;
        console.log(s1); //我今年18岁
        console.log(`我今年${age}岁`); //我今年18岁
        // 解析变量 时用 ${}

        var s2 = '我今年${age}岁'
        console.log(s2);// 我今年${age}岁

        var s3 = "我今年${age}岁"
        console.log(s3);// 我今年${age}岁

Set方法

  • 类似于数组的东西,也是按照索引下标的排列方式但是不允许使用下标并且,不会出现重复的数据
const OSet = new Set([1, 2, 1, 2, 3, 4, 4,]);
        console.log(OSet); // {1, 2, 3, 4}
        //  {1, 2, 3, 4}
        /*  0:1
            1:2
            2:3
            3:4 
         size:4
        */
        // Set 中不允许使用下标
        console.log(OSet[0]);
         undefined


        // size 类似数组的length
        console.log(OSet.size);
        //4


        // 方法

        // 1.add()

        console.log(OSet.add(5));
        // {1, 2, 3, 4, 5}

        // 2. has()
        console.log(OSet.has(2));
        //true

        // 3. delete()
        console.log(OSet.delete(2));
        //true

        // 4. clear()
        console.log(OSet.clear());
        //undefined
        console.log(OSet);
        // {size: 0}

        // 5. forEach()
        OSet.forEach((value, index, origin) => {
            /**
             *  注意: 因为 set 中的索引只能看到, 但是不能使用
             *  所以第二个参数 index 的值, 就和 第一个参数 value 一摸一样
            */
            console.log(value, index, origin);
            /* 
            1 1 Set(4) {1, 2, 3, 4}
            2 2 Set(4) {1, 2, 3, 4}
            3 3 Set(4) {1, 2, 3, 4}
            4 4 Set(4) {1, 2, 3, 4}
            */
        })


        /**
         *  Map
         * 
         *      和 Set 一样, 也是 ES6中新增的一个数据解构, 也是不支持重复数据
         *      类似于 对象
         *      map 中的属性名可以是任意类型的
        */


        const arr = [100]
        const oMap = new Map([['600', '200'], [arr, '200']])


        // 1. set() 作用: 添加数据
        oMap.set('newKey', 100)
        oMap.set('QF001', 200)

        // 2. get() 作用: 获取到这个 key 对应的 value
        console.log(oMap.get('QF001'))  // 200
        console.log(oMap.get('QF002'))  // undefined

        // 3. has() 作用: 查询数据解构中是否存在当前 key
        console.log(oMap.has('QF002'))  // false
        console.log(oMap.has('newKey')) // true

        // 4. delete() 作用: 删除数据结构中的某一项
        oMap.delete('QF001')

        // 5. clear() 作用: 清空
        // oMap.clear()
        console.log(oMap)
        //Map(4) {'600' => '200', Array(1) => '200', 'newKey' => 100,}


        // 6. forEach
        oMap.forEach((value, key, origin) => {
        //     /**
        //      *  value: 属性值
        //      *  key: 对应的属性名
        //      *  origin: 原本的数据结构
        //     */
            console.log(value, key, origin)
                /*
                0 : {"600" => "200"} 
                1: {Array(1) => "200"}
                2: {"newKey" => 100}
                */

        })