func.call(thisArg, param1, param2, ...)//func是个函数
func.apply(thisArg, [param1,param2,...])
func.bind(thisArg, param1, param2, ...)
返回值 :
call / apply : 返回func值行结果。
bind : 返回func的拷贝,并拥有指定的this值合初始参数。
参数 :
thisArg (可选) :
param1、param2(可选):传给func的参数。
call、apply、bind是挂在Function对象上的三个方法,只有函数有这些方法,例如: Object.prototype.toString就是函数,我们经常看到这样的用法Object.prototype.tostring.call(data)
执行 :
返回值 :
类数组的特徵有,可以透过索引(index)调用,如array[0];具有长度属性,可以透过for循环或forEach方法。
那类数组是什麽? 顾名思义就是具备与数组特徵类似的对象。例如下面例子 :
let arrayLike = {
0: 1,
1: 2,
2: 3,
length: 3
};
类数组比较常见在譬如,获取DOM节点的方法,返回的就是一个类数组,在函数中使用augument所获取的所有参数,也是类数组。
但注意,类数组无法使用splice,push等数组原型练上的方法,那就要用到call/apply/bind的核心理念---借用方法:
以类数组做比喻,如果它想借用Array原型链上slice的方法,可以这样:
let domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));
// 类数组对象
let arrayLike = {
0: "name",
1: "height",
length: 2
};
Array.prototype.push.call(arrayLike, "weight", "id");
console.log(arrayLike);
// {"0":"name","1":"height","2":"weight","3":"id","length":4}
function hash() {
alert( [].join.call(arguments) ); // 1,2
}
hash(1, 2);
apply直接使用数组作为参数,也省去了展开数组这一步。
const arr = [15, 6, 12, 13, 16];
const max = Math.max.apply(Math, arr); // 16
const min = Math.min.apply(Math, arr); // 6
参数数量不确定的例子 :
const obj = {
age: 24,
name: 'John',
}
const obj2 = {
age: 25
}
// 依据某些条件来决定要传入的参数数量与顺序
function callObj(thisAge, fn) {
let params = [];
if (thisAge.name) {
params.push(thisAge.name);
}
if (thisAge.age) {
params.push(thisAge.age);
}
fn.apply(thisAge, params); // 参数数量不确定,用apply
}
function handle(...params) {
console.log('params', params);
}
callObj(obj, handle); // params ["John", 24]
callObj(obj2, handle); // params [25]
经典面试题 :
for(var i = 1; i < 5; i++) {
setTimeout(function test() {
console.log(i) // 5 5 5 5 5
},i*1000)
}
原因在於等到非同步setTimeout执行时,i已经变成5了。用bind可以解决此问题 :
for(var i = 1; i < 5; i++) {
setTimeout(function test(i) {
console.log(i) // 5 5 5 5 5
}.bind(null, i),i*1000)
}
实际上这里也运用了闭包。它保存了函数this的指向(setTimeout与setInterval预设都是指向window,这边只是为了只用bind方法,null也是指向window)、初始参数,每次i边更都会被bind的闭包存起来,所以输出1~5。
class Cat {
constructor(name,callback) {
this.name = name;
this.callback = callback;
this.callback();
}
}
class Dog {
constructor(name) {
this.name = name;
this.friend = new Cat('white cat',this.run)
}
run() {
console.log(`${this.name} run with cat!`);
}
}
new Dog("white dog");
我们预期希望是显示出white dog run with cat!,但实际上显示出white cat run with cat!,原因在於当new Cat时,所传入的this.run是记忆体位子(call by reference),并没有邦定this的指向,这时候可以用bind来解决:
class Cat {
constructor(name,callback) {
this.name = name;
this.callback = callback;
this.callback();
}
}
class Dog {
constructor(name) {
this.name = name;
this.friend = new Cat('white cat',this.run.bind(this))
}
run() {
console.log(`${this.name} run with cat!`);
}
}
new Dog("white dog"); // white dog run with cat!
或是把run改为arrow function也可以:
class Cat {
constructor(name,callback) {
this.name = name;
this.callback = callback;
this.callback();
}
}
class Dog {
constructor(name) {
this.name = name;
this.friend = new Cat('white cat',this.run.bind(this))
}
run = () => {
console.log(`${this.name} run with cat!`);
}
}
new Dog("white dog"); // white dog run with cat!
<<: [寿星优惠-2] 肉肉先生 Mr.zozo #当月寿星6折
>>: day17 不懂kotlin flow资料流? 那喝杯进口奶茶吧
提醒,select仍是实验中的api,请斟酌使用 在这之前的26天,我们所用的都是我要做什麽事,就是...
其实任何技术上的选型都没有最好,就像选择程序语言一样,大家都有共识 PHP 是世界上最好的...咳,...
这是 Roblox 从零开始系列,效果章节的第三个单元,今天你将学会如何制作自己想要的粒子效果 Pa...
今天继续说滚动视差 球球的部分先在scroll_thing的下方加上球球的div <div c...
今天就我自己的经验跟大家分享一下, 培养切版技能的方向~ 第一阶段:练习什麽静态版面都要可以切出来 ...