欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

浅谈callapplybind

程序员文章站 2022-05-18 15:12:28
浅谈call apply bind call方法 第一个参数是要绑定给this的值,第二部分参数要一个一个传。(当第一个参数为nll,nudefined的时候,默认指向window) 这是一个简单的...

浅谈call apply bind

call方法

第一个参数是要绑定给this的值,第二部分参数要一个一个传。(当第一个参数为nll,nudefined的时候,默认指向window)

这是一个简单的例子:

//例1
var obj = {
    message: 'this is a people: '
}

function person(name, age) {
    console.log(this.message + name + ' ' + age)  //this is a people: xiaoming 18
}

person.call(obj, 'xiaoming', 18)

了解了它的基本语法后,我们来看这样一段代码:

//例2
    function a(a,b) {
        this.a = a;
        this.b = b;
    }
    function b() {
        this.a = 5;
        this.c = 3;
        a.call(this,1,2);
    }
    var s = new b();
    console.log(s.a+","+s.b+","+s.c);
输出是什么,是5,2,3 还是 1,2,3?
答案是后者,这是因为给b调用了a的call方法,使a的this指针指向了b,虽然我们在前面定义了b的a为5,但是在调用call方法之后又将b的a重写为了1。

上面两个都懂了 看一下第三个例子:

//例3
function a(){
        this.show = function(){alert(this.name)}
    }
    function b(){
        this.name = 'b';
    }
    var c = new a();
    var d = new b();
    c.show.call(d);//b
    alert(d.show);//undefined
    
//这段代码中,让c.show中的this指向了d,改变了匿名函数里面的this.name的值
//但是并没有给d写入c.show,所以第一个输出b第二个输出undefined

apply

接受两个参数,第一个参数是要绑定给this的值,所有参数都必须放在一个数组里面作为第二个参数传进去。(当第一个参数为null、undefined的时候,默认指向window。)

call 和apply是立即调用

bind

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

var obj = {
    name: 'xiaoming'
}

function person() {
    console.log(this.name)
}

var people = person.bind(obj)  
console.log(people)  // person() {...}
people()             //xiaoming

bind是新创建一个函数,然后把它的上下文绑定到bind()括号中的参数上,然后将它返回。所以,bind后函数不会执行,而只是返回一个改变了上下文的函数副本。(一般需要一般变量来接受它的返回值) 而原函数 printname 中的 this 并没有被改变,依旧指向全局对象 window。
bind中参数的使用:

来,我们再来看一个好玩的东西:

function fn(a, b, c) {
    console.log(a, b, c);
}
var fn1 = fn.bind(null, 'xiaoming'); //相当于已将fn1中第一个参数的值确定好了

fn('a', 'b', 'c');            // a b c
fn1('a', 'b', 'c');           // dot a b  //传入的实参依次向后对应一位
fn1('b', 'c');                // dot b c
fn.call(null, 'xiaoming');    // dot undefined undefined

对call 来说它会严格遵照将第二个及其以后的参数作为实参传入fn,而对于bind方法 fn1的实参是在bind中已确定值的参数 基础上向后排的。

三者的使用区别

都是用来改变函数的this对象的指向的;(第一个参数都是this要指向的对象)
2.都可以利用后续参数传参; bind是返回对应函数,便于稍后调用,apply、call是立即调用;

看了这么多,你或许还回小瞧它们,难道应用它们仅仅是为了改变this指向,哈哈,当然不是了!

有何用处?

1. 将类数组转化为数组

将这个之前我们先来简单回答一下类数组和数组的关系:类数组(1)拥有length属性 (2)不具有数组所具有的方法

常见的类数组有哪些呢?
参数的参数 arguments,dom 对象列表(比如通过 document.getelementsbytags 得到的列表),jquery 对象(比如 $(“p”))

原生js中的方法:
var arr = array.prototype.slice.call(类数组);

该方法等价于:
var arr = [].slice.call(类数组);

刚看到设个方法的时候,自己很是疑惑,为啥这样就可以。再网上看到一篇文章博主是这样解释的,觉得很有道理:

array.prototype.slice.call(arguments);

它会将一个类数组形式的变量转化为真正的数组。为啥呢,其实书上并没有说slice还有这样的用法,也不知道是谁发明的。slice的用法可以顺便上网查一下,就能查到。但要更正一点,网上的介绍说slice有两个参数,第一个参数不能省略。然而我不知道是我理解的问题还是咋地,上面这段代码不就是典型的没传参数吗!!!arguments是传给call的那个上下文,前面讲过,不要弄混(由于arguments自己没有slice方法,这里属于借用array原型的slice方法)。而且经过测试,若果你不给slice传参数,那就等于传了个0给它,结果就是返回一个和原来数组一模一样的副本。这之后的代码就很好理解,返回一个函数,该函数把传给bind的第一个参数当做执行上下文,由于args已经是一个数组,排除第一项,将之后的部分作为第二部分参数传给apply。

2. 数组追加(当然这里可以用数组的拼接函数concat)

var arr1 = [1,2,3];
var arr2 = [4,5,6];
var total = [].push.apply(arr1, arr2);//6
// arr1 [1, 2, 3, 4, 5, 6]
// arr2 [4,5,6]

在这里增加一个知识:
push 添加只能将添加项作为一个子元素,增加到母数组的后面

var arr1=[1,2,3,4];
    var arr2=[5,6,7,8];
    
    arr1.push(arr2);
    console.log(arr1); //(5) [1, 2, 3, 4, array(4)]

3.利用call apply做继承

function person(name,age){
    // 这里的this都指向实例
    this.name = name
    this.age = age
    this.sayage = function(){
        console.log(this.age)
    }
}
function boy(){
    person.apply(this,arguments)//将父元素所有方法在这里执行一遍就继承了
}
var dcbryant = new boy('dcbryant',22)