apply & bind
【摘要】 apply 的使用方法apply 与 call 的作用相同,基本用法如下。function fn() { console.log(this, arguments);}fn.apply('hello', ['1', '2']);// String { "hello" }// Arguments(2) ["1", "2", callee: ƒ, Symbol(Symbol.iterator):...
apply 的使用方法
apply
与 call
的作用相同,基本用法如下。
function fn() {
console.log(this, arguments);
}
fn.apply('hello', ['1', '2']);
// String { "hello" }
// Arguments(2) ["1", "2", callee: ƒ, Symbol(Symbol.iterator): ƒ]
apply 的实现原理
通过用法可以看出 apply
与 call
唯一不同的就是传参方式,call
传递给调用它的函数传参靠调用时使用参数列表的方式依次传入,而 apply
是通过数组的方式传入,只需要将 call
的代码稍加改造就可以实现 apply
。
// context 参数为要替换的 this,args 为调用 apply 函数执行的参数
Function.prototype.apply = function (context, args) {
context = context ? Object(context) : window;
context.fn = this;
// 判断是否传入参数列表,如果没传则直接执行
if (!args) return context.fn();
var result = eval('context.fn(' + args + ')');
delete context.fn;
return result;
}
bind 的使用方法
bind
函数是 Function
原型对象上的方法,bind
的作用是可以将调用它的函数内部的 this
绑定成所指定的 this
,第一个参数为指定的 this
,与 call
和 apply
不同的是,调用 bind
的函数并不会执行,而是返回一个新的函数,新的函数调用时传入的参数会和 bind
调用时传入的除第一个以外的参数进行合并,并作为调用 bind
的函数执行的参数,下面是 bind
的基本用法。
var obj = {
name: 'Shen'
};
function sayName() {
console.log(this.name);
}
var bindFn = sayName.bind(obj);
bindFn();
// Shen
var obj = {
name: 'Shen'
};
function animal(name, age) {
console.log(this.name + ' have a ' + name + ' is ' + age + ' years old.');
}
var bindFn = animal.bind(obj, 'cat');
bindFn(2);
// Shen have a cat is 2 years old.
var obj = {
name: 'Shen'
};
function Animal(name, age) {
this.name = name;
this.age = age;
}
// 动物类别为哺乳类
Animal.prototype.category = 'mammalia';
var BindFn = Animal.bind(obj, 'cat');
var cat = new BindFn(2);
console.log(cat); // Animal {name: "cat", age: 2}
console.log(cat.category); // mammalia
bind 的原理
从上面的例子已经可以看出 bind
不但能绑定 this
,收集参数,返回的函数既可以直接调用,又可以作为构造函数实例化对象,而实例化的对象的方式,bind
绑定的 this
不生效,this
指向被创建的实例,实例依然可以找到原来函数原型上的属性和方法,根据 bind
的特性,模拟实现的代码如下。
// context 参数为要绑定的 this
Function.prototype.bind = function (context) {
// this 为调用 bind 的函数
var self = this;
// 收集除了 context 以外所有的参数
var bindArgs = Array.prototype.slice.call(arguments, 1);
// 返回的新函数 fBound
function fBound() {
// 收集 fBound 的参数
var args = Array.prototype.slice.call(arguments);
// 执行调用 bind 的函数
// 若是普通函数调用,this 为 context,若是作为构造函数则 this 为实例
self.apply(this instanceof fBound ? this : context, bindArgs.concat(args));
}
// 用来继承的中间函数
function fNOP() {}
// 作为构造函数调用 fBound 时,为了实例可以找到调用 bind 函数的原型对象,进行继承
if (this.prototype) {
// Function.prototype 为函数,可以调用 bind,当时没有原型对象,所以要判断
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
}
return fBound;
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)