zoukankan      html  css  js  c++  java
  • Javascript中的this(七)

    、为什么要用this

         通过this可以在不同的上下文对象中重复使用函数

    二、this是什么

         this就是我们说的执行上下文(包含调用栈(哪里被调用)、函数的调用方式、传入的参数等信息)

    三、this的绑定规则

          1、默认绑定

             当函数调用没有引用对象时,默认this指向全局对象

          2、隐式绑定

            this指向函数的调用者

          3、显示绑定

            通过apply/call、bind绑定

          4、new绑定

             this指向new出来的对象

         5、es6的箭头函数,this指向第一个不是箭头函数的函数的父作用域

    四、测验

      1、回顾一下闭包的一个例子,搞懂词法作用域的使用

      example1: 

    var fun;
    var a = 1;
    function fn() {
       var a = 2;
       function foo() {
        console.log(a);
      }
      
       fun = foo;
    }
    
    function fun2 () {
       var a = 3;
       fun()
    }
    
    fn()
    fun2()

    foo的引用返回给了一个变量fun,fun是全局变量,一直存在内存中,fn执行完,内存不会被销毁,因为内部的变量foo还被引用着,再调用fun2,对foo中的a进行RHS查询,查找到当前词法作用中的a = 2,所以输出为2.

    example1输出结果2

    example2:

    var fun;
    var a = 1;
    function fn() {
       function foo() {
        console.log(a);
      }
      
       fun = foo;
    }
    
    function fun2 () {
       var a = 3;
       fun()
    }
    
    fn()
    fun2()  

    输出结果1  

    闭包只不过是可以让函数的词法作用域一直被引用着,让函数在执行完之后其作用域中的变量仍然能够再被使用。

    回顾一下这句话:

         动态作用域的作用域链基于调用栈,而不是代码的作用域嵌套;

         this机制让作用域有了动态作用域的特点;

         js中实质上没有动态作用域,只有词法作用域(什么是词法作用域?词法作用域是一套js引擎如何查找变量以及会在何处查找到变量的规则) 

    function t() {
      console.log(b)
    }
    
    function h() {
       var b = 4;
       t()
    }
    
    var b = 3;
    h()  

    输出结果3

    什么叫基于调用栈? 基于调用栈就应该是在查找变量时,如果没有查找到变量会基于调用栈向上一层一层的查找,直到查找到或查找至全局作用域。

    下面的例子也很清晰的表明了查找变量时,是基于词法作用域的,并不是基于调用栈。(对于详细的词法作用域解释可以看我写的作用域篇)

    var a = 0
    function bar1() { var a = 1; console.log('bar1 ',a) bar2()//调用位置 } function bar2() { console.log('bar2 ', a)//调用栈 bar1=>bar2 bar3()//调用位置 } function bar3() { //调用栈 bar1=>bar2=>bar3 console.log('bar3 ', a)//调用位置 }

    bar1()

    输出:

    bar1 1
    bar2 0
    bar3 0

    2、this的默认绑定规则

    默认绑定,无论在哪里调用函数,没有引用对象时this指向全局对象:

    function foo() {
      console.log(this.a)
    }
    
    var a=2;
    (function() {
       var a = 3;
       foo()
    })()  

     输出2  

    3、this的隐式绑定规则,可能会出现的绑定对象丢失的情况

     this指向函数的直接调用者,且只有在上一层调用才起作用

    function foo() {
       console.log(this.a)
    }
    
    function foo2(fn) {
       fn()
    }
    
    var obj = {
       a: 2,
       foo: foo
    }
    
    var a = "global"
    obj.foo() //2
    foo2(obj.foo)//global
    

     obj.foo当参数传给foo2,参数fn引用着函数foo,调用fn,this又遵循默认绑定,this指向全局对象。  

    4、显示绑定

        显示绑定就是通过apply/call、bind来改变函数的this指向;

        当给apply/call第一个参数传递null或undefined的时,默认this指向全局对象;

        

        典型应用场景,创建一个包裹函数,接受参数并返回值。

    function add (param) {
       return this.a + param
    }
    
    var obj = {
       a: 3
    }
    
    var bar = function() {
       add.apply(obj)
    }
    
    bar(2)
    //5
    

     bind方法实现:

    function add (param) {
       return this.a + param
    }
    
    var obj = {
       a: 3
    }
    
    function bind(fn, obj) {
       return function() {
           return fn.apply(obj, arguments)
      }
    }
    
    var f = bind(add, obj)
    f(2)
    //5
    

      

    5、new绑定

     

    五、关于this绑定规则的优先级

        显示绑定>隐式绑定

        new绑定>隐式绑定

        硬绑定>隐式绑定

        硬绑定>new绑定

        

        参考学习资料:

        《你不知道的javascript》上

      

  • 相关阅读:
    js中属性节点的应用
    改变属性的值的方法
    获取所有节点的一些方法的属性(有待改善)
    JS中修改属性
    获取节点的几种小案例
    在页面上点击按钮,出现弹出框
    SelectionSort,选择排序
    BubbleSort冒泡排序
    混合app
    使用(Unicode字符)让inline水平元素换行
  • 原文地址:https://www.cnblogs.com/yy95/p/9715322.html
Copyright © 2011-2022 走看看