javascript中call与this的初见

call定义

语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]]) 
定义:调用一个对象的一个方法,以另一个对象替换当前对象。 
说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。 
如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

又遇见了各种专业名词了吧,没有经过长期的文档摧残是无法快速掌握一个方法的精髓的,一起做几个小实验吧

var myName = 'goudan';

var myAge = 13;

function showMsg(msg){

  return msg + ''.toLowerCase();

}

showName(myName); // 'goudan'

这段代码很容易就能看懂,在实际开发工作中,我们会处理不同的数据集合,这时候var单一变量已经无法满足胃口,需要通过json的形式来存储数据

var person = {

  name:"kyogre",

  age:13,

  hobby:"coding"

}

var newPerson  ={

  name:'dachui',

  age:99,

  hobby:'eat'

}

function showMsg(msg){

  return msg + ''.toLowerCase();

}

showMsg(person.name) // 'kyogre'

showMsg(newPerson.name) // 'dachui'

存储数据的方式发生了改变,但是我们处理数据的方式还是那么。。。古老,如果业务复杂一点

function format(msg){

  return msg+''.toLowerCase();

}

function show(msg){

  return '信息的内容是:'+ format(msg);

}

show(person.name) // '信息内容是:kyogre'

show(newPerson.name) // '信息内容是:dachui'

显示的传递上下文对象 (穿参)使得业务越来越复杂,这种叠加会让开发变得冗余和难以解读,bug和闭包横飞

那我们看看通过this如何清晰解决问题

通常this不会指向函数自身,而是调用函数的对象主体。当然,我们可以强制让function自身成为对象主体,这个以后咱们讨论; json本身就是对象,我们是否可以这样:

var person = {

  name:"kyogre",

  age:13,

  hobby:"coding"

}

var newPerson  ={

  name:'dachui',

  age:99,

  hobby:'eat'

}

function format(){

  return this.name+''.toLowerCase();

}

问题来了,不让穿参这个format中的this指向谁呢? 指向调用format的对象本身,可是调用主体并不明确,可能是person也可能是newPerson,这时回过头看看call的定义吧:调用一个对象的一个方法,以另一个对象替换当前对象。 将函数内部执行上下文对象由原始对象替换为指定对象

var name = '我叫window';    //全局变量 非严格模式下都为 window的属性   window.name;

function format(){

  return this.name+''.toLowerCase();

}

format(); //'我叫window';

不要惊慌,本身他就是这样window会作为调用*作用域链函数的对象主体;这里的this默认为 window, 用person对象代替window这个默认this主体去执行format会怎么样呢

format.call(person);

// kyogre

format.call(newPerson);

// dachui

function show(){

  return '信息的内容是:'+ format.call(this);

}

show.call(person); // 信息的内容是:kyogre

感觉自己了解了this和call的小明,已经肆无忌惮的笑了起来,这样他就可以从繁重的回调与参数传递中解脱了,并且能够实现方法的初级模块化。可是事情并没有这么简单。。。知道的越多,不知道的就越多 ;-)


下面可以用call做一些平常的操作

function isArray(object){

  return Object.prototype.toString.call(object) == '[object Array]';

}// 借用Object原型上的toString方法来验证下对象是否是数组?

function accumulation(){

  return [].reduce.call(arguments,(a,b)=>{return a+b}

}//让不能使用数组方法的arguments类数组集合使用借用数组的reduce方法

return Array.prototype.forEach.call($$('*'),(item)=>{item.style.border = '1px solid red';}

//把类数组节点集合通过call借用数组的forEach方法实现。。。你自己在控制台用一下就知道,O(∩_∩)O~

真正决定this指向谁的并不一定是能看的见的对象,很多情况this会被隐性改变,this没有谁调用就指向谁那么简单; 如果想要深入理解,我们下次有机会谈一下执行上下文和词法作用域吧。。。。

上一篇:WPF:设置MenuItem多种不同状态图标


下一篇:android小技巧(二)