文章背景:学习前端半年后,掌握基本的vue以及其组件使用,并使用vue2.0完成两个项目的开发(一个是类似办公系统,包括权限、审批、图片展示、echarts、canvas等;一个是app项目,纯展示功能,交互特别少,html5完成);但是JavaScript开始渐渐遗忘,本文主要目的加深前面学习的js的一些知识,主要是不常用,被忘记了。
先看一个函数: ——————bind部分
function mineFun(name, age) {
console.log(name, age, this);
};
mineFun('张三', '33');
你觉得会输出什么?
mineFun('张三', '33');//不用想,看过js基础的都知道,输出
![]()
此时this 的指向是,window;
接着上面这个函数继续,
mineFun.bind(text, '张三', '33');
你觉得会输出什么?
mineFun.bind(text, '张三', '33');// 输出如下:

哈哈哈,啥也没有,再来看,

bind方法生成的是一个新的方法,需要调用这个方法才能正常运行;
打印结果:

有什么区别? 除了最后一个结果,其他都一样,此时this的指向并不是window,而是这个名叫text 的变量,本质是个字符串;
同理,把text换成obj,在新的函数中,this 的指向会再次改变

再继续看这个函数,————————apply部分

apply属性,也是改变this的指向,这一点与bind一致,区别就是,它不需要再次调用这个方法,其次它的参数必须是一个数组形式,否则就会报错:

再继续看这个函数,————————call部分

call这个属性,就更简单了,不需要再次调用,传的值也是正常的,是什么就是什么,不需要像apply一样要改成数组。
看到这里,我那个时候反正是懵逼的,什么玩意?这三个属性不基本一样嘛?为什么大佬们对这些属性都表示一定要明白,一定要懂,一定要会用。
别急,咱们看看几个实例,你可能会有些启发。等到后面遇到了,很有可能会打通你的任督二脉,忽然一下就明白了;
// 实例1,一看就懂
function ClassA(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
// 介绍自己
this.information = function information() {
console.log(this.name + '今年' + this.age + ' 性别:' + this.sex)
}
// 介绍工作
this.work = function work(workName, workName2, workName3) {
console.log(this.name + '是做:' + workName + ',' + workName2 + ',' + workName3)
}
};
function ClassB(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
// 推算年纪
this.ageAdd = function ageAdd() {
console.log(this.name + '10年后' + (10 + Number(this.age)) + '岁');
}
};
let a = new ClassA('张三', '33', '男');
a.information();//张三今年33 性别:男
let b = new ClassB('大妹子', '20', '女');
b.ageAdd();//张三10年后43岁
上面提供两个函数(类),都可以正常使用。
// 现在我想要让 这个 大妹子 介绍一下自己(就是像ClassA中的方法information),应该怎么做?
//没学call、apply、bind之前,我肯定会说,在ClassB中加一个跟ClassA一模一样的方法就行
//思考:你这个方法是永久性的还是临时性的,如果是临时性的,你自己再去写一个方法不是会很累赘嘛,
//如果是永久性的,无所谓,随你方便,都可以的
思考完看下面的方法:
// 用bind方法完成;
a.information.bind(b)();//大妹子今年20 性别:女
//用apply方法完成:
a.information.apply(b);//大妹子今年20 性别:女
// 用call方法完成
a.information.call(b);//大妹子今年20 性别:女
//上面好像apply 与 call 没啥区别,继续看,另一个方法 work;
a.work(); //张三是做:undefined,undefined,undefined
a.work.bind(b, '司机', '裁缝', '程序员')();//大妹子是做:司机,裁缝,程序员
a.work.apply(b, ['司机', '裁缝', '程序员']);//大妹子是做:司机,裁缝,程序员,这里参数必须是数组
a.work.call(b, '司机', '裁缝', '程序员');//大妹子是做:司机,裁缝,程序员
//这下看的明白不? 最上面的information 方法,使用的参数是类本身自带的参数,全部被存在了ClassA内部,可以通过this直接调用
//下面的work,引用的参数需要你自己传入, 可以清晰的看到call bind apply 的传参区别;
// 再看实例: 有关bind的传参问题
// 现在有一个LOL英雄简介,需要根据不同的武器类型,执行不同的清兵方法
function ClassC(type, name) {
if (type == '剑') {
console.log(name + '用' + type + '戳死了小兵');
} else if (type == '法杖') {
console.log(name + '用' + type + '唱死了小兵');
} else if (type == '刀') {
console.log(name + '用' + type + '砍死了小兵');
}
};
ClassC('刀', '蛮族之王');//蛮族之王用刀砍死了小兵
ClassC('法杖', '死歌');//死歌用法杖唱死了小兵
ClassC('剑', '无双剑姬');//无双剑姬用剑戳死了小兵
// 现在有人帮你把英雄人物根据武器分好类了,你只负责输出用剑的就行,你应该怎么做?
let useKnife = ClassC.bind(this, '刀');
useKnife('男刀');//男刀用刀砍死了小兵
useKnife('女刀');//女刀用刀砍死了小兵
你只需要将第一个参数固定,然后,在你需要调用时候,再次传入剩余参数就可以,是不是很方便了?不需要你每次都输入这个 武器类型
//总结:
//1.bind 可以让你在需要调用方法的时候再掉用,不会立即执行,同时它可以改变this的指向,并且会将它第二个参数及后面的参数传入这个对象中,以供使用(a.work.bind(b, '司机', '裁缝', '程序员')() 这样的形式)
// 但是,你在bind的时候,如果定义了一个参数,那么它会将这个参数默认设置为第一个参数,其他参数会被在调用的时候,往后继续排列(相当于第二个参数被你定义并占用)
2. apply 劫持一个对象的方法,继承一个对象的属性,这个实例太多了,比如让你去查看一个数组里面最大的值,你怎么干?for循环遍历比较?NONONO,太繁琐了,用apply方法一下搞定

骚不骚?好不好用?你有你想不到!!(有没有它干不了的我也不敢乱说,hhh)
3. call就不再多说,改变this指向,顺序传入对应参数(区别于apply),立即执行(区别于 bind)
任何问题请留言, 工作日全天在线,欢迎互相探讨前端知识。