JavaScript中的call和apply应用

news/2024/7/3 4:43:25

ECMAScript3给Function的原型定义了两个方法,他们是Function.prototype.call 和 Function.prototype.apply. 在实际开发中,特别是在一些函数式风格的代码编写中,callapply方法尤为有用。

call和apply区别

其实他们的作用是一样的,只是传递的参数不一样而已。
apply: 接受2个参数,第一个参数指定了函数体内this对象的指向,第二个参数为数组或者一个类数组。apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。

举个栗子:

const obj1 = {
name: 'microzz',
getName: function() {
return this.name;
}
};
 
const obj2 = {
name: 'Zhaohui'
}
 
console.log(obj1.getName()); // "microzz"
console.log(obj1.getName.call(obj2)); // "Zhaohui"
console.log(obj1.getName.apply(obj2)); // "Zhaohui"

call和apply的用途

改变this指向

call和apply可以改变this的指向,这点我们从上面这个例子中可以看出。我们还可以举一个实际当中可以遇到的情况:

有的时候我们会觉得 document.getElementById这个方法太长了,我们会尝试用一个短函数来代替它,如同prototype.js等一些框架所做过的事情,下面用代码说明:

const getId = function(id) {
return document.getElementById(id);
}
 
getId( 'id');

在Chrome、Firefox、IE10中执行会发现抛出异常,这是因为很多引擎的 document.getElementById 的方法内部需要用到this,这个this本来被期望指向document,但直接普通函数调用就指向了window。我们可以利用apply“修正” this

document.getElementById = (function(func) {
return function() {
return func.apply(document, arguments);
}
})( document.getElement);
 
const getId = document.getElementById;

Function.prototype.bind

在大部分高级浏览器已经实现了内置的Function.prototype.bind,用来指定函数内部的this指向,如果没有原生的Function.prototype.bind,我们也可以模拟一个,代码如下:

Function.prototype.bind = function(context) {
var self = this;
return function() {
return self.apply(context, arguments);
}
}
 
var obj = {
name: 'microzz'
};
 
var func = function() {
console.log(this.name); // microzz
}.bind(obj);
 
func();

这是一个简化版的,通常我们会实现得稍微复杂一点:

 
Function.prototype.bind = function() {
var self = this;
 
// 需要绑定的this上下文
var context = [].shift.call(arguments);
 
// 剩余的参数转成数组
var args = [].slice.call(arguments);
 
return function() {
return self.apply(context, [].concat.call(args, [].slice.call(arguments)));
}
}
 
var obj = {
name: 'microzz'
};
 
var func = function(a, b, c, d) {
console.log(this.name); // microzz
console.log([a, b, c, d]); // [1, 2, 3, 4]
}.bind(obj, 1, 2);
 
func( 3, 4);

借用其他对象的方法

借用构造函数

借用方法的第一种场景是“借用构造函数”,可以实现类似继承的效果:

var A = function(name) {
this.name = name;
}
 
var B = function() {
A.apply( this, arguments);
}
 
B.prototype.getName = function() {
return this.name;
}
 
var b = new B('microzz');
console.log(b.getName()); // microzz

类数组

函数参数列表arguments是一个类数组对象,虽然它有下标,但是并不是真正的数组。为了能使用数组的一些方法,我们常常会借用Array.prototype对象上的方法。
比如想往arguments中添加新元素,通常会借用Array.prototype.push
想把arguments转成真正数组的时候,可以借用Array.prototype.slice或者也可以使用ES6的Array.from

About


http://www.niftyadmin.cn/n/4254515.html

相关文章

SQL 复制过程的注意事项(转)

相关链接: 利用数据库复制技术 实现数据同步更新[摘] SQL 复制过程的注意事项(转) 1、设置共享复制目录: computer_machine//C$...//..如果服务器取消过默认的共享($)则会失败;此时新建一个目录,并赋予权限&#x…

AS3.0中自定义matedata

metadata就是元数据,反应一个类本质的属性,可以通过describeType(obj)来得到反应该对象的xml. 要自定义元数据,如[MyMatedata()]: 1 package {2 public class MyClass extends Object{3 [MyMatedata(name"ha",name2&qu…

redies常用命令

如果要使用多台redies端口就要多复制几个redies 然后将其中的redies.conf文件中端口修改一下即可 启动redies,j进入到启动文件夹子中 redis-server ./redis.conf #如果更改了端口,使用redis-cli客户端连接时,也需要指定端口,例如:…

VB中如何修改treeview的背景色

改变 TreeView 的背景 Private Declare Function SendMessage Lib "User32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long Private Declare Function GetWindowLong Lib "User3…

三台服务器信息共享,三台服务器共享使用一个弹性ip

三台服务器共享使用一个弹性ip 内容精选换一换会话保持,指负载均衡器可以识别客户与服务器之间交互过程的关联性,在实现负载均衡的同时,保持将其他相关联的访问请求分配到同一台服务器上。会话保持有什么作用呢,举例说明一下&…

关于VS2008/2010中SORT,stable_sort的比较函数中strict weak ordering

在VS2008/2010中SORT&#xff0c;stable_sort的比较函数是strict weak ordering。当比较的时候出现元素相等的情况是编译器默认必须返回false&#xff0c;而如果在自定义比较函数时&#xff0c;将相等返回true。将会出现invalid operator<的异常。 注意&#xff1a;这种异常…

lv扩展磁盘空间

2019独角兽企业重金招聘Python工程师标准>>> 1、查看磁盘空间&#xff0c;有一部分没有加进来 [rootlocalhost ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/mapper/rootvg-lvroot 29G 7.1G 21G 26% / tmpfs …

TreeView 控件应用详解

TreeView 控件应用详解TreeView控件是在VFP的数据处理中很有用的一个ActiveX 控件,但是VFP的帮助中却没有相关的说明&#xff0c;为帮助大家对这一控件有一个详细的了解&#xff0c;现将TreeView控件应用详解如下&#xff1a;一、概述  TreeView控件显示Node对象的分层列表…