js中的this指向与call、bind和apply

daoen 2018-12-02 PM 2146℃ 0条

前言

我们知道ES6中引入了箭头函数,可以极大避免 this 产生的错误,但是为了一些老代码的维护,最好还是了解一下ES5中 this 的指向和 call、apply、bind 三者的区别。

this 的指向

在 ES5 中,this 的指向始终坚持一个原理:this 永远指向最后调用它的那个对象

例子:

    var me = "windowsMe";
    function foo() {
        var me = "Jack";
        console.log(this);      // Window
        console.log(this.me); // windowsMe
    }
    foo();
    console.log(me)         // Window

    var name = "myName";
    var a = {
        name: "Canddy",
        bar: function () {
            console.log(this.name); 
        }
    }
    a.bar(); // Canddy

根据“this 永远指向最后调用它的那个对象”原则,我们看最后调用 foo 的地方 foo(),前面没有调用的对象那么就是 window在调用,这就相当于是 window.foo();而最后调用bar的是a,所以this指向a,打印的是对象a的name

使用 apply、call、bind改变this指向

例子:

    var cat = {
        word: "miaomiao",
        color: "gray",
        speak : function() {
            console.log(this.word)
        }
    }
    var dog = {
        word: "wangwang",
        color: "white"        
    }
    cat.speak(); // miao

如何用cat的say方法来显示dog的数据呢

call的写法:

cat.say.call(dog);

apply的写法:

cat.say.apply(dog);

bind的写法:

cat.say.bind(dog)();

如果直接写cat.speak.bind(dog)是达不到效果的,看到区别了吗?call和apply都是对函数的直接调用,而bind方法返回的仍然是一个函数,因此后面还需要()来进行执行才可以。

那么call和apply有什么区别呢?改写一下上面的例子。

    var cat = {
        word: "miaomiao",
        color: "gray",
        speak : function() {
            console.log(this.word + '-' + weight + '-' + height)
        }
    }
    var dog = {
        word: "wangwang",
        color: "white"        
    }
    cat.speak(); // miao-1kg-0.2m

call的写法:

cat.speak.call(dog, "1kg", "0.2m");

apply的写法:

cat.speak.apply(dog, ["1kg", "0.2m"]);

bind的写法:

cat.speak.bind(dog, "1kg", "0.2m")();
cat.speak.bind(dog)("1kg", "0.2m");

可以看到,call后面的参数与方法中是一一对应,而apply的第二个参数是一个数组,数组中的元素是和say方法中一一对应,这是两者最大的区别。而bind可以像call那样传参,也可以在调用的时候再进行传参

call/apply/bind的用途

call/apply/bind的核心理念就是借用方法
A对象有个方法,B对象因为某种原因也需要用到同样的方法,借用 A 对象的方法最便捷,借助已实现的方法,改变方法中数据的this指向,减少重复代码,节省内存。
应用案例如下:

  1. 准确判断数据类型
function is_type(data, type) {
  var alltypes = {
    "[object Null]": "null",
    "[object Undefined]": "undefined",
    "[object Object]": "object",
    "[object String]": "string",
    "[object Number]": "number",
    "[object Boolean]": "boolean",
    "[object Array]": "array",
    "[object Function]": "function",
    "[object Arguments]": "arguments"
    "[object Date]": "date",
    "[object RegExp]": "regExp",
    "[object Map]": "map",
    "[object Set]": "set",
    "[object HTMLDivElement]": "dom", 
    "[object Window]": "window",
    "[object Error]": "error",
  };
  var name = Object.prototype.toString.call(data); 
  var typename = typeObj[name] || "unknown";
  return typename === type; 
}
console.log(
  is_type({}, "object"), // true
  is_type({}, "array"), // false
);

2.通过apply获取数组最值

var num_arr = [1, 2, 12, 0];

const max = Math.max.apply( Math, num_arr ); // 12

const min = Math.min.apply( Math, num_arr ); // 0

其它应用场景还有类数组调用数组方法等,抓住方法借用概念就好,这里就不做过多介绍。

标签: javascript

非特殊说明,本博所有文章均为博主原创。

评论啦~