上一篇2018年3月面试心得《跨域问题》es6
话说我在面试的时候,有那么几天,不知道是中了什么邪,面试的几家公司开始疯狂的问我this,
各类的this,绕着弯的问我this,后来我作梦都是this、this、this……你妹的this!面试
那么先从面试官会怎么问你来讲吧。segmentfault
其实这个虽然题目我记得很少了,可是真的问起来仍是很恶心的。
由于一旦代码丢出来了,还会涉及到继承,构造函数,原型链,闭包等一系列问题在后面等着你,面试管为了掏你的底细会一问再问,问到你懵逼。api
那么咱们先来讲说第一个问题,做用域和上下文。跨域
什么是做用域?数组
问得好,我也不知道,待我查一下………………闭包
做用域是在运行时代码中的某些特定部分中变量,函数和对象的可访问性。换句话说,做用域决定了代码区块中变量和其余资源的可见性。
emmmm…………很差理解的话,我说一个比喻吧。
如今我为一个房子专门定一个木窗窗沿,这个窗沿只适合这个房子里面全部须要用的地方,其余房子不能用,那么这个房子就是我木窗的做用域~~~app
就像我在异步
function 房子(){ var 木窗; }
个人木窗只属于个人房子,我不能够在房子的外面,例如小区里面直接拿到个人木窗,我必须进入房子去找这个木窗,这是不能够改变的做用域。函数
而后咱们再来看一下
var 景色 = '大海' function 房子() { var 景色 = '大草原'; this.木窗 = function() { console.log(景色) } 木窗() } 房子()
请问这个时候输出的景色是什么呢~
机智的小朋友确定会说是大草原~~~
为何呢~
由于景色我从下往上找啊,找到最近的一张图我就不用继续找了,拿出来用就好啦。
怎么样,惊不惊喜,意不意外,刺不刺激~~~
js中有全局做用域,函数做用域,块级做用域(es6)。
很好解释,我全部地方均可以调用的到的,就像路边的广告牌,咱们均可以看获得,不须要想办法进谁家里去看。
是产生在函数中的,一个函数内部会出现一块做用域。能够这么理解,函数是咱们的房子,咱们站在房子外面(全局)的时候,没法看到房子里面的东西。可是咱们站在房子里面(函数内部),是能够去透过窗子凑凑整个外面的世界的。
哇塞这个就厉害了,在咱们es6里面,新增了一些像let、const之类的语法,能够产生一个块级做用域。
你们应该都作过一个简单的题目,就是一个for循环里面丢一个setTimeout,下面放出代码。
for(var i = 0; i<5; i++) { setTimeout(function() { console.log(i) }, 1000) }
咱们看一下这一个题目,首先会让你回答打印出来的是什么。
机智的小伙伴确定会回答:5 5 5 5 5
为何咧,由于这个var的i成了全局的,并非只在循环里面去使用,setTimeout是一个异步函数,因此咱们执行完了for才会去console.log。
这个还涉及到同步异步之类的,会单独开一章来说,光是基础都已经让人头昏眼花,啊西吧~
那若是咱们要让他12345怎么办呢,能够把i保留下来作一个闭包传入,还有一个最方便的办法就是用let来声明他。
ps: 不过通常面试官会跟你说不要用es6,给我一个es5的办法2333333333
=3=
另外说一下let和const和var主要的区别:
就像
const i = 10; i = 9; // 这样是不行的!!! const u = {a: 'a',b: 'b'} u.b = 'c' // 这样是能够的
其实很好理解,不过我仍是举个?吧……
我const一个大爷,我改变这个大爷的属性,相似给他换个衣服或者换个鞋子,但是大爷仍是大爷因此不会报错。
可是我const一个妹子,完事了把妹子改为了大爷,那我不依,报错。
那什么是上下文呢?
这个也好理解,好比我窗户装在客厅,看到的是客厅里面的景色,装到了厨房,就是厨房的景色,固然这个上下文是能够更改的,我能够个这个窗沿里面贴上珠穆拉玛峰的照片,那么这个上下文就被我改了。
function 房子() { var 景色 = '大草原'; this.木窗 = function() { console.log(this.景色) } 木窗() } 房子()
你猜打印出来的是什么~~~
固然是undefind!
想什么呢~不会觉得是大草原吧~
为何咧,由于他的this变了。
下面我把这行代码改成直接打印this,打印出来的是一个window。
为何?由于我调用房子的地方在window下,我调用了房子,房子调用了木窗,因此this成了window。
那么咱们刚刚是否是在房子里面给了一张大草原的画呢,这是否是在房子外面(window层)就找不到了呢,因此是个window。
哈哈哈哈哈
若是你在这里就昏了,那么必定要往下看,否则你永远都搞不清楚this到底会指向哪里。
再说一下第三个问题,改变this的指向。
这个其实也很简单,call或者apply均可以,这个本身看api去~考官会问你两个的区别的,乖宝宝要本身看文档哦~
最后一题,绕着弯子让你说this是啥。
既然你看到了这里,那么正题开始了!!!
问得好,我本身也懵逼。
不要紧,咱们能够一块儿捋一捋。
容老夫先沐浴更衣,焚香祈祷大家不要被我带歪了。
首先,跟我一块儿读一遍下面的两句话(固然,若是有补充能够留言):
1: 谁调用指向谁,没有谁就是window2: 除了call、apply、bind和箭头函数
首先咱们在全局下打印一下this,控制台输出的是window,这个没有疑问吧~
咱们再来经过函数调用一下
function 房子() { this.木窗 = function() { console.log(this) } 木窗() } 房子()
那么咱们再回过头去看刚刚的房子窗子。
咱们是哪里开始调用房子的?
固然是window,其实房子()就等同于window.房子()。
因此呢,调用房子的是window,那么房子最底下会调用木窗,因此真正的调用者被抓出来了。
window => 房子 => 木窗
函数的调用者就是this,请抓住始做俑者,这道题就是window这个小婊渣,就是他~
那么咱们再看下一个。
经过对象的属性来调用:
var obj = { say: function() { console.log(this); } }; obj.say();
打印的结果是: {say: ƒ}
谁调用就指向谁,这个obj.say()的执行方法调用者是前面的obj,因此当前的这个this指向了obj。
再看一个
var obj = { say: function() { var hehe = function() { console.log(this) } hehe() } }; obj.say();
这个this指向了window。
为何?由于这个hehe并非obj上面的属性,没有找到调用者是谁,因此默认指向window。
下面咱们来看一下其他几个指向谁。
call和apply你们都知道,能够改变this的指向。
var obj = {a: 'a'}; function b() { console.log(this) } b.apply(obj)
打印结果:{a: "a"}
call差很少,二者差异只是参数传的不同,一个能够传数组。
具体状况,宝宝们文档走一波~
而后再来看一下bind
哇塞这个也厉害了
直接上代码
var axiba = {hehe: 'hehe'} var obj = { a: 'a', b:function() { console.log(this) }.bind(axiba) }; b() // 或者 var axiba = {hehe: 'hehe'} var obj = { a: 'a', b:function() { console.log(this) } }; var u = obj.b.bind(axiba) u()
执行的是神马~
固然是指向axiba~
最后一个,就是es6的箭头函数
我要单独为箭头函数加个粗
官网逛一逛,发现了几句话。
箭头函数有几个使用注意点。(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不能够看成构造函数,也就是说,不可使用new命令,不然会抛出一个错误。
(3)不可使用arguments对象,该对象在函数体内不存在。若是要用,能够用 rest 参数代替。
(4)不可使用yield命令,所以箭头函数不能用做 Generator 函数。
上面四点中,第一点尤为值得注意。this对象的指向是可变的,可是在箭头函数中,它是固定的。
要理解其实也很容易,首先……
上代码……
function foo() { setTimeout(() => { console.log('id:', this.id); }, 100); } var id = 21; foo.call({ id: 42 });
代码中,setTimeout的参数是一个箭头函数,这个箭头函数的定义生效是在foo函数生成时,而它的真正执行要等到 100 毫秒后。若是是普通函数,执行时this应该指向全局对象window,这时应该输出21。可是,箭头函数致使this老是指向函数定义生效时所在的对象(本例是{id: 42}),因此输出的是42。
因此之后有人问你es6的箭头函数的this和es5函数中的this的区别,那么就是es6不可改变,始终指向定义的对象,es5是根据调用环境的,若是没有调用者,默认window。
由于考官会出得题目千千万,题海战术几乎无用,我以前也是做用域和上下文傻傻分不清,虽然如今也懵懂阶段,不过学无止尽嘛。
有什么表达不当的地方,悄悄告诉我哦~
么么哒