从面试题分析this
来源:互联网 发布:python编程入门下载 编辑:程序博客网 时间:2024/06/07 05:07
这几天工作贼忙~项目页面逻辑需要大的整改,一直忙到没时间看一些其他东西(回家倒头就想睡觉),好不容易抽了一个早上的时间,马上来学习一下this整改关键字。(毕竟这个是js中的基础中的基础,也是重难点)
OK废话不多说,还是老规矩,先上一个面试题,找了蛮久的,而且有个人的解释特别清晰(而且还涉及到了作用域和闭包),我就直接贴一下他的解释,然后自己再补充一点其他的知识点,扩展一下。
var number=2;var obj={ number:4, fn1:(function(){ var number; this.number*=2; number=number*2; number=3; return function(){ var num=this.number; this.number*=2; console.log(num); number*=3; alert(number); } })(), db2:function(){ this.number*=2; }}var fn1=obj.fn1;alert(number);fn1();obj.fn1();alert(window.number);alert(obj.number);大家有答案了么?
下面是别人的答案,十分的清晰,如果你对this有所了解的话,应该一下就能看明白,如果看不明白,也没关系,可以再看一下我后面的一些总结。
var number=2;var obj={ number:4, fn1:(function(){ // 匿名函数1 var number; this.number*=2;// (1) number=number*2;// (2) number=3; return function(){ // 匿名函数(2) var num=this.number; this.number*=2; console.log(num); number*=3; alert(number); } })(), db2:function(){ this.number*=2; }}var fn1=obj.fn1; // (3)alert(number);// (4)fn1();// (5)obj.fn1();// (6)alert(window.number);alert(obj.number);•当定义obj的时候执行了匿名函数1,此时处于全局作用域内,因此上下文this是window。执行完语句(1)导致全局变量number的值变为4;执行语句(2)时临时变量number还没有被赋值,所以是NaN,但下一句会将其赋值为3;最后,匿名函数1返回了匿名函数2,因此obj.fn1=匿名函数2。(注意匿名函数2里面会用到临时变量number,老生常谈的闭包)•来到语句(3),这句会把fn1这个变量赋值为obj.fn1,也就是匿名函数2•由于全局变量number已经在语句(1)中变为了4,所以语句(4)弹出的对话框结果为4•语句(5)执行的是fn1(),它与执行obj.fn1()的区别是两者this不一样。前者为null,而后者this为obj。但是又由于JS规定,this为null时相当于全局对象window,所以这句代码执行时函数的this为window。在匿名函数2里会将全局变量number更新为8,同时将匿名函数1中被闭包的临时变量number更新为9•语句(6)的效果在上面已经分析过了,this是obj,所以obj.number更新为8,闭包的number更新为27
下面就是我自己的总结:
如果我们看完题目和答案还是一头雾水的话就可以先”预习“一下,然后再回过头去看题目。
__________________________________________________________________________________________________________________
1.谁调用这个函数或方法,this关键字就指向谁。
2.在JS中,一个函数中的this
只有到了执行的时候才能确定是什么,例如函数声明的时候里面的this其实是null,js规定为null的时候其实就是window(浏览器的环境下)。在执行的时候如果这个函数是某个实例对象下的一个 方法则指向这个实例对象,否则也是window。
3.函数的调用方式:普通函数调用,作为方法来调用,作为构造函数来调用,使用apply/call方法来调用。
*普通函数的话很简单,就是相当于这样去调用:
/****************************************************/
var fun(){
console.log(this); //[object Window]
}
fun();
这里的其实把fun当作一个全局函数去调用,它的对象是window,所以根据我们第2个知识点,它声明的时候调用它的对象是window,调用的时候也是window,所以它这里的this总是window。
*作为方法来使用:
/******************/
var o={
fun:function(){
console.log(this);
}
}
o.fun();// [object Object]
这里使用的时候是o去调用fun这个函数,所以this指向的就是o这个对象。
如果我这里在上面这个题目上做一个变形:
var a=o.fun;
a(); //[object Window]
没错,这里使用的时候a其实是window的一个属性,当去调用a()的时候,就相当于window去调用,this就又指向了window。
*作为构造函数来使用:
/************************/
function Fun(){
this.fun=function(){
console.log(this);
}
}
var o=new Fun();
o.fun(); // [ object Object]
这里运用到了new,我以前在原型的面试题中说过,new这个过程的最后一步就是把this指向实例出来的对象,也就是我这里的o。
*使用apply/call方法来调用,其实函数也是对象,call和apply其实就是函数原型上的一种方法,它能调用这个函数。
/****************/
function fun(){
console.log(this);
}
fun.call();
fun.apply();
这两种方式都是调用这个函数,其实函数的调用都可以看作是用call和apply来执行,用.apply( )或者.call()来代替我们的( ).
总结起来就是fun( ) --> fun.call( );
obj.fun( ) --> obj.fun.call(obj);
4.我们其实可以通过call,apply,bind(这个是js的方法,不同于jq中的bind)方法来改变我们this的所指向对象。
首先说一下call和apply:
(上面的call和apply参数的问题,第一个参数如果传了,那么这个函数里面的this就指向这个传进来的第一个参数,如果不传则是window,后面的参数就是这个函数需要的参数)
call与apply是函数都具有的一个方式,其作用是可以改变其this的指向,其调用方式有所不同。
call和apply第一个参数都一样,不过apply后面的参数以数组形式传递建议使用。
我们来看一下这个题目:
var x = 10; var obj = { x: 20, f: function(){ console.log(this.x); var foo = function(){ console.log("foo:"+this.x); } foo(); } };obj.f();
执行结果是 20 ,10
为什么呢?因为foo是var 出来的一个变量,它不是从属于obj,其实是window的属性,所以它里面的this是指向window的,但是我们这里可以用call来把它的this来改变一下。
foo.call( obj )
这样之后结果就变成了20,20 (这个题目是不是跟面试题有异曲同工之妙呢?)
介绍了call的方法,我们知道了它可以调用函数,可以改变this指向,那么我们就可以让B对象去调用A对象的方法了。
可以看下面这个例子:
function FruitA(n1,n2){ this.n1=n1; this.n2=n2; this.change=function(x,y){ this.n1=x; this.n2=y; } } var fruitA=new FruitA("cheery","banana"); var FruitB={ n1:"apple", n2:"orange" }; fruitA.change.call(FruitB,"pear","peach"); console.log(FruitB.n1); //输出 pear console.log(FruitB.n2);// 输出 peach
我们这里可以看到对象FruitB是没有change的方法的,它是存在于FruitA中,我们这里就是实例化了一个FruitA的对象,然后利用call去改变this指向,指向了FruitB,然后去改变FruitB中的n1和n2的值。
上面说完了call和apply,这里要说一下bind,!!!这个bind是ES5出来的函数(IE8及一下是不支持的),并不是JQ的bind,所以JQ现在都提倡不用bind,用on了。
大家可以看看这个博客:http://www.cnblogs.com/iyangyuan/p/4493322.html
- 从面试题分析this
- 从面试题分析变量作用域
- 从一些公司面试题分析理解分析未来情况
- 从一道面试题分析Linux进程+IO缓冲区机制
- 从一道面试题分析Thread.interrupt方法
- 从一道面试题分析Linux进程+IO缓冲区机制
- 从一道面试题分析c++的多态特性
- 【Java面试题】之类加载:从面试题分析Java类加载机制
- WK面试题分析
- 一道面试题分析
- java面试题分析
- 一道面试题分析
- 2,面试题分析
- 部分面试题分析
- struts2面试题分析
- Struts2 面试题分析
- Struts2 面试题分析
- c++面试题分析
- 银行业务调度系统的实现
- HDU 3001 Travelling
- ASM 翻译系列第十七弹:ASM Internal ASM Disk Directory
- SublimeText3注册码
- 手机直播开发——推动直播发展新纪元
- 从面试题分析this
- 打印整数的递归例程
- Jackson 工具类使用及配置指南
- 简单的音乐播放
- php实现文件下载代码
- Tomcat – Java.Lang.OutOfMemoryError: PermGen Space
- Java协程框架-Kilim字节码剖析
- flexbox属性justify-content失效
- IDEA怎样导入eclipse项目