前端学习笔记--apply()和call()

2018-02-09  本文已影响0人  沧澈

在ECMAscript标准标准中定义了call()和apply()两种方法,能够改变函数的上下文,也就是函数内部this的指向

call: 英 [kɔːl] 美 [kɔl]

Function.call(obj , arg1, arg2, ...)
obj:这个对象将代替Function类里this对象
params:这个是一个参数列表

apply英 [ə'plaɪ] 美 [ə'plaɪ]

Function.apply(obj,args)
obj:这个对象将代替Function类里this对象
args:这个是数组,它将作为参数传给Function(args-->arguments)

call()和apply()都能通过点语法的调用方式,来指定上下文执行这个函数
例子:

function test() {
    console.log(this.name);
}

var obj = {
    name: '小明',
    age: 12
};

test.call(obj);
test.apply(obj);

控制台输出结果为:

小明
小明

call()和apply()唯一的区别就是接受的参数不一样,call的参数形式是一个参数列表,apply的参数是一个数组

例子:

function test(a,b,c) {
    console.log(a+b+c);
    console.log(this.name);
}

var obj = {
    name: '小明',
    age: 12
};

test.call(obj,1,2,3);
test.apply(obj,[1,2,3]);

控制台输出结果为:

6
小明
6
小明

在非严格模式下,第一个参数传递为null或者undefined时,函数内的this会指向默认的宿主对象,在浏览器中是window

例子:

var test=function(){
    console.log(this===window);
}

test.apply(null);
test.call(undefined);

控制台输出结果为:

true
true

例子:

function Animal(name){   
    this.name = name;   
    this.showName = function(){   
        console.log(this.name);   
    }   
}   
 
function Cat(name){  
    Animal.call(this, name);  
}   
 
var cat = new Cat("Black Cat");   
cat.showName();

控制台输出结果为:

Black Cat

在实际开发中,经常会遇到this指向被不经意改变的场景。
有一个局部的fun方法,fun被作为普通函数调用时,fun内部的this指向了window,但我们往往是想让它指向该#test节点。
例子:

window.id="window";
document.querySelector('#test').onclick = function(){
    console.log(this.id);
    var fun = function(){
        console.log(this.id);
    }
    fun();
}

控制台输出结果为:

test
window

解决:

window.id="window";
document.querySelector('#test').onclick = function(){
    console.log(this.id);
    var fun = function(){
        console.log(this.id);
    }
    fun.call(this);
}

控制台输出结果为:

test
test

也可以这样做,不过在ECMAScript 5的strict模式下,这种情况下的this已经被规定为不会指向全局对象,而是undefined
例子:

window.id="window";
document.querySelector('#test').onclick = function(){
    var that = this;
    console.log(this.id);
    var fun = function(){
        console.log(that.id);
    }
    fun();
}

function func(){
    "use strict"
    alert ( this );   // undefined
}
func();

控制台输出结果为:

test
test

这里把符合以下条件的对象称为类数组

常见类数组有 arguments,NodeList!

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

控制台输出结果为:

[1, 2, 3, 4]

这样就往arguments中push一个4进去了

同样push方法没有提供push一个数组,但是它提供了push(param1,param,…paramN) 所以同样也可以通过apply来装换一下这个数组,即:

var arr1=new Array("1","2","3"); 
var arr2=new Array("4","5","6"); 
Array.prototype.push.apply(arr1,arr2); 
console.log(arr1);

控制台输出结果为:

["1", "2", "3", "4", "5", "6"]

也可以这样理解,arr1调用了push方法,参数是通过apply将数组装换为参数列表的集合.

(function(){
  var maxNum = Math.max.apply(null,arguments);
  console.log(maxNum);
})(34,2,56);

控制台输出结果为:

56
console.log(Object.prototype.toString.call(123)) 
console.log(Object.prototype.toString.call('123')) 
console.log(Object.prototype.toString.call(undefined)) 
console.log(Object.prototype.toString.call(true)) 
console.log(Object.prototype.toString.call({}))
console.log(Object.prototype.toString.call([])) 
console.log(Object.prototype.toString.call(function(){})) 

控制台输出结果为:

[object Number]
[object String]
[object Undefined]
[object Boolean]
[object Object]
[object Array]
[object Function]

注:文章内容参考网络,后整理。

上一篇下一篇

猜你喜欢

热点阅读