• 修改this指向(bind、call 和 apply)


    一、bind

    首先:

    var alertWrite = document.write;
    alertWrite('who am I?');
    

    这两行代码的运行结果是什么呢?不要急着回答,看完下面的内容再回答。

    bind 的其中一个用法就是:绑定函数,使其无论怎么样调用都用相同的 this

    看下面的例子:

    var obj = {
        getThis: function() {
            console.log(this);
        }
    };
    obj.getThis();
    var getThisCopy = obj.getThis; getThisCopy();

    运行结果如下:

    通过上述例子我们会发现,虽然是 getThisCopy 是复制了 obj 的 getThis 方法,但是他们所属的对象却不一样。在对象里面,所有的 this 都指向对象本身,而在全局作用域定义的变量的 this 指向 Window。

     所以,下面这段代码的运行结果,能猜的出来结果吗?

    1 var obj = {
    2     num: 100,
    3     numFun: function() {
    4         console.log(this.num);
    5     }
    6 };
    7 var numFunCopy = obj.numFun;
    8 numFunCopy();

    bind 的存在就是 为了解决 this 不能够指向原来的问题。

    所以,试试这段代码:

     1 var alertWrite = document.write;
     2 alertWrite.bind(document)('hello');
     

    4 var obj = { 5 getThis: function(){ 6 console.log(this); 7 } 8 } 9 var getThisCopy = obj.getThis; 10 getThisCopy.bind(obj)(); 11 12

    13 var obj = {
    14     num: 100,
    15     numFun: function(){
    16         console.log(this.num);
    17     }
    18 }
    19 var numFunCopy = obj.numFun;
    20 numFunCopy.bind(obj)();

    总结bind使用方法:

    fun.bind(thisArgument, argument1, argument2, ...)

    thisArgument:在 fun 函数运行时指定的 this 值,如果绑定函数时使用 new 运算符构造的,则该值将被忽略。

    argument1, argument2, ...:指定的参数列表。

    返回值:具有指定 this 值和初始参数的给定函数的副本

    使用1:创建绑定函数,使函数无论怎么样调用,都有相同的 this 值

     1 this.x = 9; 
     2 var module = {
     3   x: 81,
     4   getX: function() { return this.x; }
     5 };
     6 
     7 module.getX(); // 返回 81
     8 
     9 var retrieveX = module.getX;
    10 retrieveX(); // 返回 9, 在这种情况下,"this"指向全局作用域
    11 
    12 // 创建一个新函数,将"this"绑定到module对象
    13 // 新手可能会被全局的x变量和module里的属性x所迷惑
    14 var boundGetX = retrieveX.bind(module);
    15 boundGetX(); // 返回 81

    使用2:偏函数,使一个函数拥有预设值。

    但是 bind 是 ES5 的内容,有一定的兼容性问题。

    解决bind兼容性方案(1)

     1 //解决IE10以下不支持Function.bind
     2 if (!Function.prototype.bind) {
     3     Function.prototype.bind = function(oThis) {
     4         if (typeof this !== "function") {
     5             throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
     6         }
     7         var aArgs = Array.prototype.slice.call(arguments, 1),
     8             fToBind = this,
     9             fNOP = function() {},
    10             fBound = function() {
    11                 return fToBind.apply(this instanceof fNOP && oThis ? this : oThis,
    12                     aArgs.concat(Array.prototype.slice.call(arguments)));
    13             };
    14         fNOP.prototype = this.prototype;
    15         fBound.prototype = new fNOP();
    16         return fBound;
    17     };
    18 }

    解决bind兼容性方案(2)

    1 if (!function() {}.bind) {
    2     Function.prototype.bind = function(context) {
    3         var self = this
    4             , args = Array.prototype.slice.call(arguments);     
    5         return function() {
    6             return self.apply(context, args.slice(1));    
    7         }
    8     };
    9 }

    二、call

    语法:fun.call(thisArgument, argument1, argument2, ...)

    thisArgument:在 fun 函数运行时指定的 this 值。在非严格模式下,该函数 this 指定为 null 和 undefined ,则 this 值会自动只想全局对象,同时只为原始值的 this 会指向该原始值的自动包装对象。

    argument*:指定的参数列表。

    返回值:调用该方法的返回值,如果没有,则返回undefined。

    使用1:使用 call 方法来实现继承

    使用2:使用 call 调用匿名函数,方法为for循环传入不同的对象

    使用3:指定上下文 this

    三、apply

    语法:fun.apply(thisArg [, argsArray])

    thisArg:可选,在非严格模式下,如果 this 值设置为 null/undefined,则 this 指向去全局对象(浏览器中就是 window 对象),同时为原始值(数字,字符串,布尔值)的 this 会指向该原始的包装对象。

    argsArray:可选。数组或者类数组对象(从ES5开始可以使用类数组对象)。

    返回值:调用有指定this值和参数的函数的结果。

    使用:其使用跟 call() 非常相似,只是提供参数的方式不同。

  • 相关阅读:
    *洛谷P1858 多人背包
    ZOJ3469 Food Delivery
    Hdu5115 Dire Wolf
    Codevs 2765 隐形的翅膀
    Hdu4055 Number String
    Codevs 1300 文件排版
    洛谷 P1412 经营与开发
    Codevs 4357 不等数列
    codevs 3333 高级打字机
    Bzoj 1086: [SCOI2005]王室联邦
  • 原文地址:https://www.cnblogs.com/z-one/p/7230477.html
Copyright © 2020-2023  润新知