• js中this指向问题(call,apply,bind)


    call、apply、bind的作用是改变函数运行this的指向

    如果你传的 context 就 null 或者 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined)

    函数运行时,有三种调用方法。

    方法调用模式

     var a = 1
     var obj1 = {
       a:2,
       fn:function(){
         console.log(this.a)
       }
     }
     obj1.fn()//2  

    this是指obj1这个对象,obj1.fn()实际上是obj1.fn.call(obj1);

    函数调用模式

    var a = 1
    var obj1 = {
        a:2,
        fn:function(){
            console.log(this.a)
        }
    }
    var fn1 = obj1.fn
    fn1()//1
    obj1.fn是一个函数function(){console.log(this.a)},此时fn1就是不带任何修饰的函数调用,function(){console.log(this.a)}.call(undefined)
    回调函数也属于函数调用
    setTimeout(function() {
        console.log(this)//window
        function fn(){
            console.log(this)//window
        }
        fn()
    }, 0);
    构造器调用模式

    new一个函数时,背地里会将创建一个连接到prototype成员的新对象,同时this会被绑定到那个新对象上

    function Person(name,age){
    // 这里的this都指向实例
        this.name = name
        this.age = age
        this.sayAge = function(){
            console.log(this.age)
        }
    }
    
    var dot = new Person('Dot',2)
    dot.sayAge()//2

    上面的三种方法可以这样理解

    obj1.fn() 
    obj1.fn.call(obj1);//指向当前对象
    
    fn1()
    fn1.call(null)//指向window对象
    
    f1(f2)
    f1.call(null,f2)//指向新对象

    call

    call 方法第一个参数是要绑定给this的值,后面传入的是一个参数列表。当第一个参数为null、undefined的时候,默认指向window。

    var arr = [1, 2, 3, 89, 46]
    var max = Math.max.call(null, arr[0], arr[1], arr[2], arr[3], arr[4])//89

    可以这么理解:

    obj1.fn() 
    obj1.fn.call(obj1);
    
    fn1()
    fn1.call(null)
    
    f1(f2)
    f1.call(null,f2)

    看一个例子:

    var obj = {
        message: 'My name is: '
    }
    
    function getName(firstName, lastName) {
        console.log(this.message + firstName + ' ' + lastName)
    }
    
    getName.call(obj, 'Dot', 'Dolby')

    apply

    apply接受两个参数,第一个参数是要绑定给this的值,第二个参数是一个参数数组。当第一个参数为null、undefined的时候,默认指向window。

    var arr = [1,2,3,89,46]
    var max = Math.max.apply(null,arr)//89

    可以这么理解:

    obj1.fn() 
    obj1.fn.apply(obj1);
    
    fn1()
    fn1.apply(null)
    
    f1(f2)
    f1.apply(null,f2)

    是不是觉得和前面写的call用法很像,事实上apply 和 call 的用法几乎相同, 唯一的差别在于:当函数需要传递多个变量时, apply 可以接受一个数组作为参数输入, call 则是接受一系列的单独变量。
    看一个例子:

    var obj = {
        message: 'My name is: '
    }
    
    function getName(firstName, lastName) {
        console.log(this.message + firstName + ' ' + lastName)
    }
    
    getName.apply(obj, ['Dot', 'Dolby'])// My name is: Dot Dolby

    可以看到,obj 是作为函数上下文的对象,函数 getName 中 this 指向了 obj 这个对象。参数 firstName 和 lastName 是放在数组中传入 getName 函数。

    call和apply可用来借用别的对象的方法,这里以call()为例:

    var Person1  = function () {
        this.name = 'Dot';
    }
    var Person2 = function () {
        this.getname = function () {
            console.log(this.name);
        }
        Person1.call(this);
    }
    var person = new Person2();
    person.getname();       // Dot

    从上面我们看到,Person2 实例化出来的对象 person 通过 getname 方法拿到了 Person1 中的 name。因为在 Person2 中,Person1.call(this) 的作用就是使用 Person1 对象代替 this 对象,那么 Person2 就有了 Person1 中的所有属性和方法了,相当于 Person2 继承了 Person1 的属性和方法。

    对于什么时候该用什么方法,其实不用纠结。如果你的参数本来就存在一个数组中,那自然就用 apply,如果参数比较散乱相互之间没什么关联,就用 call。像上面的找一组数中最大值的例子,当然是用apply合理。

    和call很相似,第一个参数是this的指向,从第二个参数开始是接收的参数列表。区别在于bind方法返回值是函数以及bind接收的参数列表的使用。

    • bind返回值是函数
    var obj = {
        name: 'Dot'
    }
    
    function printName() {
        console.log(this.name)
    }
    
    var dot = printName.bind(obj)
    console.log(dot) // function () { … }
    dot()  // Dot

    bind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数。而原函数 printName 中的 this 并没有被改变,依旧指向全局对象 window。

  • 相关阅读:
    jdk源码调试进去形参没有值
    proxy 简化版本
    spering getBean(),IOC
    彻底清除挖矿程序
    Kworkerd恶意挖矿分析
    怎么让 Android 程序一直后台运行,像 QQ 一样不被杀死
    linux 系统下使用socket进行本地进程间通信
    linux i2c 的通信函数i2c_transfer在什么情况下出现错误
    Java Socket网络编程常见异常(转)
    踩过的坑系列之InputStream.read(byte[])方法
  • 原文地址:https://www.cnblogs.com/cqy1125/p/11727893.html
Copyright © 2020-2023  润新知