上一篇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。
由於考官會出得題目千千萬,題海戰術幾乎無用,我以前也是做用域和上下文傻傻分不清,雖然如今也懵懂階段,不過學無止盡嘛。
有什麼表達不當的地方,悄悄告訴我哦~
麼麼噠