zoukankan      html  css  js  c++  java
  • JS-箭头函数及其this的指向和改变this指向(call apply bind)

    2,箭头函数
        function(){}        ---   ()=>{}     箭头函数
        function(e){}       ---   e =>{}     箭头函数
        function(){一行}    ---   ()=>一行    箭头函数
        function(e){一行}   ---   e =>一行    箭头函数
    
        特点:1,this指向与一般的function函数不同
            声明式  function fun(){}           this指向,window
            赋值式  var fun = function(){}     this指向,window
            forEach()循环                      this指向,window
            定时器,延时器  setInterval(function(){} , 时间)
                                                this指向,window
            对象中的函数 const obj = {fun:function(){}}
                                                this指向,obj对象
            事件处理函数 标签.addEventListener(事件类型,function(){})
                                                this指向,标签对象
                                            
            箭头函数的this指向,是父级程序的this指向
                如果父级程序有this指向,指向向的就是父级程序的this指向
                如果父级程序没有this指向(对象,数组是没有this),指向的是window
            
            2,箭头函数,无法改变this指向
    
    3,改变this指向
        函数.call(参数1,其他参数...)
            立即执行函数,并且改变函数的this指向为参数1表示的内容
            其他参数,是原始函数的实参,多个实参使用逗号间隔
        函数.apply(参数1,[数组参数])
            立即执行函数,并且改变函数的this指向为参数1表示的内容
            数组参数,是原始函数的参数,多个参数以数组的单元的形式存储
        函数.bind(参数1)
            不会立即执行函数,而是生成一个新的函数
            新函数,参数,程序内容,都与原始函数相同
            只是this改变为参数1表示的内容

    一.箭头函数

    所谓的箭头函数
    是函数的另一种语法形式
    const fun = function(){}     普通函数
    const fun = ()=>{}           箭头函数
    将匿名函数的部分,从 function(){} 写成 ()=>{} 的形式
    
    如果函数只有一个参数,可以不写()
    const fun = function(e){}     普通函数
    const fun = e => {}           箭头函数
    
    如果执行体中只有一行代码,可以不写{}
    const fun = e=>{console.log(e)}    普通箭头函数
    const fun = e=> console.log(e)     不写{}箭头函数
    
    
    const oDiv = document.querySelector('div');
    
    // 普通函数
    oDiv.addEventListener('click' , function(){
        console.log('我是div标签')
    })
    
    // 箭头函数
    oDiv.addEventListener('click' , ()=>{
        console.log('我是div标签');
    })
    
    // 只有一个参数,可以不写(),直接定义一个参数
    oDiv.addEventListener('click' , e=>{
        console.log(e);
    })
    
    // 只有一行代码,不写{}
    oDiv.addEventListener('click' , e=>console.log(e) )

    二.箭头函数的this指向

    箭头函数中的this指向
    为什么要有箭头函数?
    是为了配合明天要讲的面向对象和构造函数
    在箭头函数中,this指向有特殊的意义,专门可以用来配合构造函数和面向对象编程思想
    
    在箭头函数中,this指向,父级程序的this指向
    如果父级程序有this指向,那么箭头函数指向的就是父级程序的this
    如果父级程序没有this指向,那么指向的就是window
    
    关于this的总结
    1,普通的function函数
        声明式 --- window
        赋值式 --- window
        forEach循环 --- window
        定时器,延时器 --- window
        对象中的函数 --- 对象本身
        事件绑定事件处理函数 --- 绑定事件的标签
    
    2,箭头函数的this指向
        父级程序的this指向
        如果父级程序有this指向(父级程序也是函数),this指向的就是父级程序的this指向
        如果父级程序没有this指向(数组,对象....),this指向的是window
    
    复习this指向
    
    ***************普通函数的this指向**************
    声明式,赋值式/匿名函数,对象中函数,绑定的事件处理函数
    this都是指向的调用函数时,之前定义的内容
    
    1,声明式 --- 指向的是window
    function fun1(){
        console.log(this);
    }
    
    fun1();
    
    2,匿名函数/赋值式 --- 指向的是window
    const fun2 = function(){
        console.log(this);
    }
    fun2();
    
    3,定义在对象中的函数 --- 指向的是对象
    const obj = { 
        fun3 : function(){
            console.log(this);
        }
    }
    obj.fun3();
    
    4,绑定的事件处理函数 --- 指向的是绑定事件处理函数的标签
    const oDiv = document.querySelector('div');
    // oDiv.onclick = function(){
    //     console.log(this);
    // }
    
    oDiv.addEventListener('click' , function(){
        console.log(this);
    })
    
    
    *******************箭头函数的this指向********************
    与普通函数的this指向是有区别的
    箭头函数中,this的指向是父级程序的this指向
    当前的程序,箭头函数的父级程序,
    如果没有,则this指向的就是window
    
    oDiv.addEventListener('click' , ()=>{
        console.log(this);
    })
    
    // 对li进行操作
    const oLis = document.querySelectorAll('li');
    oLis.forEach(function(item,key){
        // console.log(this);  // 输出的是forEach的函数的this指向
        // 箭头函数的this,是父级程序,forEach()的this,是window
        item.addEventListener('click' , ()=>{
            // console.log(key,this);
        })
    })
    
    forEach()中 函数的this指向,就是window
    const arr = [1,2,3,4,5,6];
    arr.forEach(function(){
        console.log(this);
    })
    
    
    const obj = {
        // 普通函数,this指向对象
        fun1 : function(){console.log(this)},
        // 箭头函数this指向是,父级程序
        // 父级程序是对象
        // 只有函数有this,obj对象没有this
        // 父级程序没有this,指向的是window
        fun2 : ()=>{console.log(this)},
    
        // fun3是一个普通函数,this指向的是obj对象
        fun3 : function(){
            // fun4,是一个箭头函数,this指向的是父级程序的this指向
            // 父级程序是fun3,fun3的this是对象,fun4箭头函数的this也是对象
            const fun4 = ()=>{console.log(this)};
            fun4();
        }
    }
    obj.fun1();
    obj.fun2();
    obj.fun3();

    三.改变this指向

    重点:箭头函数,不能改变this指向,只有普通function函数,能改变this指向
    
    改变this指向的方法
    
    1, call()方法
    语法: 函数.call(参数1,其他参数....可以是多个或者没有 )
    作用: 调用并且执行函数,同时,将函数的this指向,定义为指定的内容(参数1)
            参数1,是改变的this的指向
            其他参数,是原始函数的实参,原始函数有几个形参,此时就要对应的输入几个实参,没有形参,就没有实参
    
    2, apply()方法
    语法: 函数.apply(参数1,参数2)  只有两个参数
            参数1:改变的this的指向内容
            参数2:原始函数的实参,必须是一个数组的形式,将实参定义成数组的单元
    其他用法和作用于 .call是相同的
    
    总结: call方法与apply方法,作用,效果,都是完全一致的
            只是对于原始函数的参数赋值方法,不同
            call方法是通过其他多个参数来实现
            apply方法是通过一个数组参数,来实现
            两个方法没有本质的区别,爱用哪个用那个
    
    3, bind()方法
    语法: const 变量 = 函数.bind(参数1);
    不是立即执行函数(下一篇博客有介绍 立即执行函数)
    生成一个新的函数,这个新的函数是改变this指向之后的新的函数
    参数1,定义的要改变的的this指向
    其他参数,一般不定义,是使用函数原有的形参
    
    总结:
        call apply 都是立即执行函数
            参数1,都是改变的this指向
            其他参数,是原始函数的形参(可以有,也可以没有)
        bind 不是立即执行函数,是生成一个新的函数
            参数1,是改变的this指向
            就使用原始函数的形参
    
    
    const obj1 = {
        name:'张三',
        age:18,
        sex:'',
    }
    
    const obj2 = {
        name:'李四',
        fun2 : function(){
            console.log(this);
        }
    }
    // 对象中的函数,this指向的是这个对象,obj2
    obj2.fun2();
    // 改变this指向,指向的是obj1这个对象
    // 代用,并且执行fun2这个函数,同时将fun2的this指向,从原始的obj2,改变为obj1
    obj2.fun2.call(obj1);
    
    // 带有参数的函数,this指向的改变
    
    // 定义的带有参数的普通函数
    function fun3(name,age,sex){
        console.log(name,age,sex,this);
    }
    // 执行时,输出实参,此时this指向是window
    fun3('张三',18,'');
    
    // 改变this指向 , call方法
    fun3.call(obj1,'李四',20,'');
    
    // 改变this指向 , apply方法
    fun3.apply(obj1 , [ '王五' , 20 , '不知道' ])
    
    // bind方法,不是立即执行函数,而是定义生成一个新的函数
    // 新生成的函数,this指向是参数1
    // 新生成的函数,形参是原始函数fun3的形参
    const fun4 = fun3.bind(obj1);
    
    fun4('王二麻子' , 100 , '不详');

    四.注意事项特别说明

    面向对象和面向过程
    
    从面向过程,改造成面向对象
    1,获取的数据,标签对象,要以参数的形式,定义给构造函数和实例化对象
        获取标签对象时,一般获取父级,传参父级,在构造函数中,通过父级标签,获取子级标签独享
    2,必须非常非常非常注意 this的指向,一般在面向对象中 都是使用箭头函数
        如果万一不能清楚地知道this指向,可以先输出 this
    3,其他步骤和思路基本相同,没有区别
    
    总结:
    1,改不改箭头函数,看内部是否需要 指向实例化对象的this 
        如果需要,可以改箭头函数,或者是提前存储this指向
        如果不许需要,改不改箭头函数都行
        一切以实现程序为最终需求,程序能执行就可以
    2,之前面向过程的是参数,数据等,
        现在是面向对象编程,要在对象的属性中,定义参数数据
        也就是通过 构造函数 this.属性 = 属性值 语法来定义需要获取的参数数据
    3,定义在构造函数方法中的一些变量数据,并不是定义在实例化对象中的属性
        没有必须写成 this.属性 = 属性值 的形式
        只要写成普通的变量定义即可 
        使用时,也是直接使用变量,不需要添加this
    4,在构造函数的方法中,调用其他的函数方法
        语法形式 应该是 实例化对象.函数方法名称()
        在构造函数中,使用this来指向实例化对象,写成 this.函数方法名称()

    转载: https://blog.csdn.net/DcTbnk/article/details/105419682

  • 相关阅读:
    Oracle Flashback Table
    新上线MySQL数据库规划
    Spark启动流程(Standalone)- master源码
    Spark启动流程(Standalone)-分析
    Spark Netty 通信框架解析
    Spark内核概述
    SparkStreaming DStream转换
    Spark-Core RDD依赖关系
    Spark-Core RDD中函数(变量)传递
    Spark-Core RDD行动算子
  • 原文地址:https://www.cnblogs.com/plBlog/p/14004696.html
Copyright © 2011-2022 走看看