JavaScript我学之八善变的this---函数执行上下文
本文是金旭亮老师网易云课堂的课程笔记,记录下来,以供备忘。
函数执行上下文
当函数运行时,通过this,函数可以获取它运行所需的外界环境的相关信息(比如某变量的值,另一个对象的引用等)。
this引用的对象会”变的”!
每次对函数的调用都有一个上下文对象,this关键字引用它。如果函数归属于某个对象,则this关键字将引用此对象,它就是本次函数调用的上下文。
1 var obj = { 2 func: function () { 3 console.info("func():this=" + this); 4 } 5 }; 6 obj.func();//func():this=[object Object] 7 var ref = obj.func; 8 ref();//func():this=[object Window]
函数对象的call方法
- 所有函数都有一个call方法,此方法可以动态地指定函数调用的上下文对象(this引用它)
- call方法的第一个参数代表本函数运行时的上下文对象,后面跟的参数函数调用的实参(如果有的话)。
1 window.color = "red"; 2 var o = { color: "blue" }; 3 function sayColor() { 4 console.info(this,this.color); 5 } 6 sayColor(); //window "red" 7 sayColor.call(this); //window "red" 8 sayColor.call(window); //window "red" 9 sayColor.call(o); //Object "blue"
函数对象的apply方法
- call可以接收可变数目的参数,而apply仅能接收两个参数,第一个是context对象,另一个是参数数组,数组中可以包容多个参数。
- apply方法 参数为context对象与数组
1 function Person(name) { 2 this.name = name; //this.name 属性Person对象,而name 是实参,两个虽同名但是不同个体。 3 } 4 var say = function (message) { 5 console.info((this.name || '无名氏') + 6 "说:“" + (message || '我什么也不想说了') + "”。"); 7 } 8 say(); //无名氏 说:“ 我什么也不想说了“ 9 var p1 = new Person("qiu"); 10 say.apply(p1, ["这是qiu说滴"]); //qiu说:“这是qiu说滴”。 11 window.name = "唐僧"; 12 say.apply(null, ["你想说你就说嘛,你不说我就说了"]); //唐僧说:“你想说你就说嘛,你不说我就说了”。
回调函数中的this
被回调函数showTime的执行上下文,与回调函数setInterval的一致,都是window.示例
1 <h4 id="output"></h4> 2 <script type="text/javascript"> 3 ////什么是回调? 4 var output = document.getElementById('output'); 5 //被回调的函数 6 function showTime() { 7 console.info(this); 8 if (!!output) { //转换成boolean值 9 output.innerHTML = new Date().toLocaleString(); 10 } 11 } 12 //负责回调的函数 13 setInterval(showTime, 1000); 14 </script>
回调函数的执行上下文对象
那么问题来了,当回调一个对象的方法时,如果此方法需要访问对象中的属性会怎么样?
1 var obj = { 2 outputElem: document.getElementById('output'), 3 showTime: function () { 4 this.outputElem.innerHTML = new Date().toLocaleString(); 5 } 6 }; 7 //当回调一个对象的方法时,如果此方法需要访问对象中的属性 8 //则会报告出错 9 setInterval(obj.showTime, 1000);
window对象中没有outputElem属性,因此,showTime()方法执行出错!
必须使用bind()方法,指定回调 函数在特定的上下文对象上执行。
1 //设定被回调的函数,绑定到obj上 2 var callbackFunc = obj.showTime.bind(obj); 3 ////现在工作正常了! 4 setInterval(callbackFunc, 1000);