首页 技术 正文
技术 2022年11月12日
0 收藏 707 点赞 3,512 浏览 2608 个字

thiscallapply

this

和其他语言不同,JavaScript的this总是指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。

this的指向

除去不常用的with和eval,this的指向大致可分为以下四种:

  • 作为对象的方法调用

  • 作为普通函数调用

  • 构造器调用

  • Function.prototype.call或Function.prototype.apply调用

作为对象的方法调用

当函数作为对象的方法被调用时,this指向该对象。

var obj={
a:1,
getA:function(){
alert(this===obj);//true
alert(this.a);//1
}
};obj.getA();

作为普通函数调用

当函数不作为对象的属性被调用时,也就是普通函数方式,此时this总是指向全局对象。在浏览器中,这个全局对象是window。

window.name='globalName';var getName1=function(){
return this.name;
};var myObject={
name:'sven',
getName:function(){
return this.name;
}
};var getName=myObject.getName;alert(getName1());//globalName
alert(getName());//globalName

构造器调用

当用new运算符调用函数时,该函数总会返回一个对象,通常情况下,构造器里的this就指向返回的这个对象。

var MyClass=function(){
this.name='sven';
};var obj=new MyClass();
alert(obj.name);//sven

但是如果构造器显式地返回了一个object类型的对象,那么此次运算结果最终会返回这个对象,而不是我们之前期待的this:

var MyClass=function(){
this.name='sven';
return{
name:'anne';
}
};var obj=new MyClass();
alert(obj.name);//anne

如果构造器不显式地返回任何数据,或者是返回一个非对象类型的数据,就不会造成上述问题:

var MyClass=function(){
this.name='sven';
return 'anne';
};var obj=new MyClass();
alert(obj.name);//sven

call和apply调用

call和apply可以动态的地改变传入函数的this:

var obj1={
name:'sven',
getName:function(){
return this.name;
}
};var obj2={
name:'anne'
};console.log(obj1.getName());
console.log(obj1.getName.call(obj2));

call和apply

call和apply作用一模一样,区别在于传入参数的形式不同。apply接受两个参数,第一个参数指定了函数体内this对象的指向,第二个参数第二个参数为一个带下标的集合,这个集合可以为数组,也可以为类数组。

JavaScript的参数在内部就是用一个数组来表示的,从这个意义上来说,apply比call的使用率更高。call是包装在apply上的一颗语法糖,如果我们明确知道函数接受多少个参数,而且想一目了然地表达形参和实参的对应关系,那么也可以用call来传送参数。

当使用call或者apply时,如果我们传入的第一个参数是null,函数体内的this会指向默认的宿主对象,在浏览器中就是window,但如果是在严格模式下,函数体内的this还是为null。

有时候我们使用call或者apply的目的并不在于指定this的指向,二十另有用途,比如借用其他对象的方法,那么我们就可以传入null来代替某个具体的对象。

call和apply的用途

改变this的指向

Function.prototype.bind

        Function.prototype.bind=function() {
var self=this,
context=[].shift.call(arguments),//需要绑定的this上下文
args=[].slice.call(arguments);//剩余的参数转成数组
return function(){
return self.apply(context,[].concat.call(args,[].slice.call(arguments)));//执行新的函数体的时候,会把之前传入的context当作新函数体内的this,并且组合两次分别传入的参数,作为新函数的参数
}
}; var obj={
name:'sven'
}; var func=function(a,b,c,d){
alert(this.name);
alert([a,b,c,d]);
}.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('sven');
console.log(b.getName());

第二种场景:函数的参数列表arguments是一个类数组对象,虽然它也有下标,但她并非真正的数组,所以不能进行排序操作或者往集合里添加一个新的元素。这种情况下我们常常会借用Array.prototype对象上的方法。比如想往arguments里插入一个元素,通常会借用Array.prototype.push:

(function(){Array.prototype.push.call(arguments,3)})(1,2);

在操作arguments时,我们经常非常频繁地找Array.prototype借用方法。

  • 转化为数组:Array.prototype.slice

  • 截去头元素:Array.prototype.shift

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,088
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,564
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,412
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,185
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,821
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,905