apply bind call 详解 和 实际应用

带你深刻理解js 中 apply bind call

  1. 网上有不少博客写了这方面的文章, 可是最近又从新复习一下,作一下理解
  2. 写了几个例子帮助你们理解一下
  3. 在项目中的做用

做用

  1. 改变函数执行时的上下文
  2. 改变函数运行时的this指向

this 永远指向最后调用它的那个对象

来理解一下 this 的做用域javascript

var name = "window";

    var dog = {
        name : "小黄"
        eat: function () {
            console.log(this.name)
        },
        say: function () {
            setTimeout(  function () {
                // 默认指向window对象,若是在严格模式下, 默认是undefined
                this.eat()
            },100);
        }
    };
    dog.say()   // this.eat is not a function
复制代码

当 setTimeout 执行的时候 最后调用的 对象是 window, window 没有 eat 的方法因此 出错java

在写一个例子理解一下 this 永远指向最后调用它的那个对象 这句话windows

var name = "windows";
    var dog = {
        name: "小黄",
        say : function () {
            console.log(this.name);      // windows
        }
    }
    var fn = a.say;
    fn();
复制代码

为何 dog 做用域下 有 name 属性, 还输出了 全局的 name 呢数组

  1. this 永远指向最后调用它的那个对象
  2. fn = a.say 并无执行 当 fn() 执行的时候 是 window 的做用域下

解决以上两个问题

咱们这里只拿一个 call修改做用域 解决这个问题数据结构

var name = "window";

    var dog = {
        name : "小黄"
        eat: function () {
            console.log(this.name)
        },
        say: function () {
            setTimeout(  function () {
                this.eat()
            }.call(dog),100);
        }
    };
    dog.say()   // this.eat is not a function
复制代码

在调用的时候修改 this 的指向手动吧 this 指向 dog 的做用域app

现实场景中的应用

  1. 构造函数中 方法的公用dom

    function Animal (name){
            this.name = name
            this.food = food
        }
        Animal.prototype = {
            eay: function(){
                console.log(this.name + 'eat: ' + this.food)
            }
        }
        var dog = new Person('小黄''火腿')
        dog.eay()
    复制代码

    上面代码会输出 小黄eat: 火腿函数

    var cat = {
        }
    复制代码

    咱们定义了一个构造函数 那若是咱们有有一个对象也想使用 Animal 原型中 eay 的方法咋办, 不能在从新写一遍 eay 方法吧ui

    // 1 call
        person.showName.call(cat, '小猫咪''鱼');
        // 2 apply
        person.showName.apply(cat, ['小猫咪''鱼']);
        // 3 bind
        person.showName.bind(cat, '小猫咪''鱼')();
    复制代码

    具体的怎么传参, 他们的差异是啥 能够看一下 MDN 上的文档说明this

  2. 将伪数组转化成 数组 arguments 也是伪数组 咱们知道在看 jq 的源码中 常常经过 call apply 的 形式 转换成真正的数组

    var element = {
            0: 'div',
            1: 'p',
            2: 'span',
            length: 3
        }
    复制代码

    这里必定要注意(数据结构必须是以数字为下标并且必定要有length属性 且必须是number类型) 你们能够实际看一下 dom 的伪数组

    见证奇迹的时刻

    // slice 能够将 伪数组转换成真正的数组
        var arr = Array.prototype.slice.call(element);
    复制代码
  3. 求数组中的最大和最小值

    var arr = [34,5,3,6,54,6,-67,5,7,6,-8,687];
        // 数组没有 max 的方法 可使用 Max 中的方法
        Math.max.apply(Math, arr);
    复制代码
  4. 判断变量类型

    function isArray(obj){
            return Object.prototype.toString.call(obj) == '[object Array]';
        }
        isArray([]) // true
        isArray('false') // false
    复制代码
相关文章
相关标签/搜索