1.call、apply的用法
call、apply、bind这三个都是函数自带的方法(Function.prototype原型的方法),它是Javascript引擎内在实现的,因此每个方法都有apply和call属性,这三个方法能改变函数内部this的指向,当第一个参数是null时不改变this指向。
call()
这个方法的第一个参数表示this指向的对象,后面的所有参数都是函数的参数
//所有变量都是window的属性
var item = "abc";
//其实是Function的实例
function fn(){
console.log(this.item);
}
fn();
//Object的实例
var data = {
item:123
}
//改变了this的指向
fn.call(data);
apply()
這個方法和call方法的作用都是相同的,只不过在传递参数时候,call方法可以传递多个参数,而apply方法只能传递两个参数,并且第二个要求是一个数组。
/*apply在对象中使用*/
function Product(){
}
Product.prototype={
binddom:function(a,b){
console.log(a+b);
},
}
Product.prototype.binddom.apply(null,[1,2])
var p = new Product();
p.binddom.apply(null,[1,2]);
/*apply在函数中的使用*/
function fun(num1,num2,num3){
var arr = Array.prototype.slice.call(arguments);
console.log(arr.length);
}
fun.apply(null,[5,6,7]);
2.call函数模拟实现
实现第一版 函数无参数
/*实现第一版*/
Function.prototype.myCall = function(context){
//给context添加属性指向this
context.fun = this;
//执行
context.fun();
//删除添加的属性
delete context.fun;
}
var obj = {
value:1
}
function fun(){
console.log(this.value);
}
fun.myCall(obj);
实现第二版 函数有参数用伪数组遍历,同时用eval执行函数
/*实现第二版 加参数*/
Function.prototype.myCall1 = function(context){
//给context添加属性指向this
context.fun = this;
//参数数组
var params = [];
for(var i = 1; i < arguments.length; i++){
params.push('arguments['+i+']');
}
//执行
eval('context.fun('+params+')');
//删除添加的属性
delete context.fun;
}
var obj1 = {
value : 2
}
function fun1(aa,bb){
console.log(this.value+"参数aa"+aa +"参数bb"+bb);
}
fun1.myCall1(obj1,'tom',12);
实现第三版 如果context为null 时把context指向window
/*实现第三版 如果context为null 时把context指向window
所有全局的函数和变量都是window的属性*/
Function.prototype.myCall2 = function(context){
var context = context || window;
//给context添加属性指向this
context.fun = this;
//参数数组
var params = [];
for(var i = 1; i < arguments.length; i++){
params.push('arguments['+i+']');
}
//执行
eval('context.fun('+params+')');
//删除添加的属性
delete context.fun;
}
var obj2 = {
value : 2
}
function fun2(aa,bb){
console.log(this.value+"参数aa"+aa +"参数bb"+bb);
}
fun2.myCall2(obj2,'jack',9);
网友评论