美文网首页
this的典型场景和call,apply,bind的总结

this的典型场景和call,apply,bind的总结

作者: 广告位招租 | 来源:发表于2019-03-11 23:22 被阅读0次

    this的典型场景

    注意: 函数使用场合的不同,this的值会发生变化。但是有一个总的原则,那就是this指的是,调用函数的那个对象

    this是函数执行时在函数内部作用域创建的临时对象,只在当前函数执行过程中有效,代表持有当前函数的对象,其具有以下四种典型案例;

    1. 作为对象的方法调用。

    2. 构造器调用。

    3. Function.prototype.call 或 Function.prototype.apply 调用。

    4. 作为普通函数调用。

    1. 对象内部函数类型属性值,此类函数执行时,this代表当前对象
    var car = {
        name:"didi",
        say:function(){
            console.log(this);   //这里this代表当前对象
            console.log(this.name);    //这里返回didi
        }
    }
    

    其扩展为(典型事件场景)

    document.onclick = function(){    dom0级事件绑定
        console.log(this)       // 这里当点击时返回document
    }
    
    1. 构造函数中this表示新对象
    function Person(name.age){
        this.name = name;
        this.age = age;
    }
    var per = new Person("tom",28);
    
    1. call和apply中,this代表第一个参数,也就是要为函数扩充的作用域
    var cup = {
        size:"300ml",
        price:"10$"
    };
    function showPrice(){
        console.log(this.size);
        console.log(this.price);
    }
    
    showPrice.call(cup);    //这里函数调用对象,将对象cup中的参数赋值给函数,所以上方函数可以正常打印
    

    以下扩充call和apply的典型案例

    <div></div>
    <div></div>
    <div></div>        //创建几个div
    <div></div>
    
    <script type="text/javascript">
    
    var doms = document.getElementsByTagName("div");     // 提取节点并存入类数组doms中,其类似数组但是没有数组的方法
    console.log(doms);   //打印
    var newDoms = Array.prototype.slice.call(doms,1,2);    //这里用Array的原型调用call函数,将doms变成完全体的数组,然后调用slice截取下标从1开始到2为止的字符存入var newDoms中
    // 使用call或者apply都可以为伪数组提供数组方式
    
    1. 普通函数之中,或者是其他场景,this都代表window
    function fn(){
        console.log(this);
    }
    fn();
    //函数嵌套函数
    function out(){
        console.log(this);                   //这里的this返回的都是window
        function inner(){
            console.log(this);
        }
        inner();
    }
    out();
    
    
    

    call,apply和bind

    ECAMScript 3 给 Function 的原型定义了两个方法,它们是 Function.prototype.call 和 Function. prototype.apply。它们的作用一模
    一样,区别仅在于传入参数形式的不同。

    apply 接受两个参数,第一个参数指定了函数体内 this 对象的指向,第二个参数为一个带下 标的集合,这个集合可以为数组,也可以为类数组,apply 方法把这个集合中的元素作为参数传 递给被调用的函数:

    var func = function( a, b, c ){
        console.log ( [ a, b, c ] ); 
    };
    func.apply( null, [ 1, 2, 3 ] ); // 输出 [ 1, 2, 3 ]
    

    call 传入的参数数量不固定,跟 apply 相同的是,第一个参数也是代表函数体内的 this 指向, 从第二个参数开始往后,每个参数被依次传入函数:

    var func = function( a, b, c ){
        console.log ( [ a, b, c ] ); 
    };
    func.call( null, 1, 2, 3 ); // 输出 [ 1, 2, 3 ]
    

    当使用 call 或者 apply 的时候,如果我们传入的第一个参数为 null,函数体内的 this 会指 向默认的宿主对象,在浏览器中则是 window:

    var func = function( a, b, c ){
        console.log ( this === window ); 
    }
    func.apply( null, [ 1, 2, 3 ] ); // 输出 true
    

    call和apply的用途

    改变 this 指向

    // 栗子1
    var obj1 = { 
        name: 'obj1'
    };
    var obj2 = { 
        name: 'obj2'
    };
    
    window.name = 'window';
    
    var getName = function(){ 
        alert ( this.name );
     };
    };
    
    getName(); 
    getName.call(obj1)
    getName.apply(obj2)
    
    // 栗子2
    // 如前文,可以稍作修改
    document.getElementById("button").onclick = function() {
    
        changeValue.call(this);
    
        function changeValue() {
            console.log(this.id) // button
        }
    };
    

    借用其他对象的方法

    (function(){
        Array.prototype.push.call( arguments, 3 ); console.log ( arguments ); // 输出[1,2,3]
    })( 1, 2 );
    

    Function.prototype.bind

    let obj = {
        name: 'obj'
    }
    
    let getName = function() {
        console.log(this.name)
    }.bind(obj)
    
    getName() // obj
    

    相关文章

      网友评论

          本文标题:this的典型场景和call,apply,bind的总结

          本文链接:https://www.haomeiwen.com/subject/kpcwpqtx.html