apply(),call()和bind()

本文深入解析JavaScript中bind、call、apply三个函数的作用与区别,包括如何改变函数内部this的指向,参数传递的不同方式,以及bind创建绑定函数的特点。通过实例演示了如何使用这些函数解决实际问题,如求最大值、判断数据类型和翻转字符串。

1.apply(),call()和bind()的相同点

三者都可以把一个函数应用到其他对象上;都是用来改变函数内部的this的指向的;

2.call()和apply()

相同点:都是调用一个对象的一个方法,用另一个对象替换当前对象(功能相同)
例如: B.call(A, args1,args2);即A对象调用B对象的方法 ,且向调用的方法传入args1,args2......参数
            F.apply(G, arguments);即G对象应用F对象的方法,且向调用的方法传入arguments参数

不同点:参数书写方式不同
call()的第一个参数是this要指向的对象,后面传入的是参数列表,参数可以是任意类型,当第一个参数为null、undefined的时候,默认指向window;
apply():第一个参数是this要指向的对象,第二个参数是数组

3.bind()

bind会创建一个新函数,称为绑定函数,当调用这个函数的时候,绑定函数会以创建它时传入bind()方法的第一个参数作为this,传入bind()方法的第二个及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数;

不同点是call,apply是修改函数的作用域,即修改this指向,并且立即执行,而bind不会立即执行,而只是返回一个改变了上下文的函数副本;

4.示例分析

var stu1={
    name:"小明",
    age:18,
    sex:"男",
    say:function (school,grade,score,address) {
        console.log(`姓名:${this.name},性别:${this.sex},
                     年龄:${this.age}岁,学校:${school},
                     年级:${grade},成绩:${score}
                     住址:${address}`)
    }
}

var stu2={
    name:"小花",
    sex:"女",
    age:16
}

stu1.say.call(stu2,"黄埔一中","高一",88)
stu1.say.apply(stu2,["衡水中学","高二",98,"北京","123@qq.com"])
stu1.say.bind(stu2,"黄冈高中","高三",100,"湖北")()

注意:传入的参数可以多于、少于、等于实际参数

5.难点分析

5.1使用apply求最大值

var arr=[2,46,81,100,999]
console.log(Math.max.apply(arr, arr));   //999
console.log(Math.min.apply(arr, arr));   //2

 第一个arr表示让arr借用max这个方法,第二个arr表示传给max的数据

5.2.1利用call()判断数据类型

在判断数据类形式使用typeof,一般不是太准确的,我们可以使用Object.prototype.toString.call()方法来判断一个数据的数据类型

console.log(Object.prototype.toString.call("qq"));             //[object String]
console.log(Object.prototype.toString.call(12));               //[object Number]
console.log(Object.prototype.toString.call(false));            //[object Boolean]
console.log(Object.prototype.toString.call(null));             //[object Null]
console.log(Object.prototype.toString.call(undefined));        //[object Undefined]
console.log(Object.prototype.toString.call([]));               //[object Array]
console.log(Object.prototype.toString.call({}));               //[object Object]
console.log(Object.prototype.toString.call(function () {}));   //[object Function]

console.log(Object.prototype.toString.call(NaN));              //[object Number]

我们可以利用上面的输出的内容进行封装一个函数,以达到判断输入数据的基本类型

function getType(x) {
    var obj=Object.prototype.toString.call(x)
    var sub=obj.substr(8)  // substr(start,length)  start 要抽取的子符串的起始下标,
                           // length 截取的长度,如果不写则表示从start开始截取到最后
    var type=sub.substr(0,sub.length-1).toLowerCase();
    return type;
}

console.log(getType(12));      //number
console.log(getType({}));      //object
console.log(getType("hello")); //string

5.2.2使用call翻转字符串

//思路:将字符串转化为数组,借用数组中的reverse,将字符串翻转过来
var str = "abcdefg";
console.log(Array.prototype.reverse.call(str)); //错误,即引用类型错误,只有数组才能使用reverse这个方法

//方法一:这种方法内有使用call()
var arr =  Array.from(str).reverse().join("") //将字符串转化为数组,在进行翻转,然后在进行拼接
console.log(arr) //gfedcba
console.log(typeof arr) //string

//方法二:
var rs = Array.prototype.reverse.call(str.split("")).join("");
//split(separator,howmany) 方法用于把一个字符串分割成字符串数组。
//如果把空字符串 ("") 用为参数那么字符串中的每个字符之间都会被分割
console.log(rs);               //gfedcba
console.log(typeof arr)        //string

5.3 bind()

//js
var oBtn=document.getElementById("btn")
var oDiv=document.getElementById("div")

oBtn.onclick=function () {
    console.log(this.innerHTML);     //江上之清风
}.bind(oDiv)

//html
<button id="btn">按钮</button>
<div id="div">江上之清风</div>

但由于ie6~ie8不支持该方法,所以若想在这几个浏览器中使用,我们就要模拟该方法,这也是面试常考的问题,模拟的代码如下

if (!function() {}.bind) {
    Function.prototype.bind = function(context) {
        var self = this
            , args = Array.prototype.slice.call(arguments);
            
        return function() {
            return self.apply(context, args.slice(1));    
        }
    };
}
--------------------- 
作者:一只新人 
来源:优快云 
原文:https://blog.youkuaiyun.com/u014267183/article/details/52610600 
版权声明:本文为博主原创文章,转载请附上博文链接!


 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值