一、使用 typeof bar === "object" 判斷 bar 是否是一個對象有神馬潛在的弊端?如何避免這種弊端?
使用 typeof 的弊端是顯而易見的(這種弊端同使用 instanceof):
let obj = {};
let arr = [];javascript
console.log(typeof obj === 'object'); //true
console.log(typeof arr === 'object'); //true
console.log(typeof null === 'object'); //true
從輸出結果能夠知道,typeof bar==='object'不能準確的判斷bar就是一個object.能夠經過 Object.prototype.toString.call(bar) === "[object Object]"來避免這種弊端:
console.log(Object.prototype.toString.call(obj)); //[object Object]
console.log(Object.prototype.toString.call(arr)); //[object Array]
console.log(Object.prototype.toString.call(null)); //[object Null]
Object.prototype.toString相關信息:http://www.jb51.net/article/79941.htm複製代碼
二、(function(){
var a = b = 3;
})();
console.log(b)//3;
console.log(a)//a is not defined;
等同於:
(function(){
b=3;
var a=b;
})();
三、 知識點:www.jb51.net/article/771…
var myObject = {
foo: "bar",
func: function() {
var self = this;
console.log(this.foo);
console.log(self.foo);
(function() {
console.log(this.foo);
console.log(self.foo);
}());
}
};
myObject.func();//bar bar undefined bar;
注意:被誰調用,不是處於誰的做用域,即便在做用域css
一、func是由myObject調用的,this指向 myObject。html
二、self指向myObject,至關於 myObject的this的副本。前端
三、這個當即執行匿名函數表達式(IIFE)是由window調用的,this指向 window 。java
四、IIFE的做用域處於myObject.func的做用域中,本做用域找不到self變量,沿着做用域鏈向上查找self變量,找到了指向 myObject對象的 self。
例二:
function outer(){
this.i = 10;
console.log(this.i);
this.text1=(function(){
console.log(this.i);
}());
this.text2=function(){
console.log(this.i);
};
};
outer();//10 10
console.log('**')
var ex=new outer();
ex.i='test';
ex.text2();//test
ex.text1();//Uncaught TypeError: ex.text1 is not a function(…)node
this是據以執行的對象,就是誰調用的,例二是在window中調用,this天然指向window,nginx
四、for(var i = 0; i < 5; i++) {
console.log('test');
setTimeout(function() {
console.log(i);
}, 0);
}
//每個setTimeout在執行時,會返回一個惟一ID,
輸出內容是:5 5 5 5 5
setTimeout是異步,js的事件運行機制是先執行同步的,再執行異步,此時的i=5,使用var定義的變量i的做用域是函數,那麼console i的值爲for 循環的i值。
咱們就必須藉助閉包的特性,每次循環時,將i值保存在一個閉包中,當setTimeout中定義的操做執行時,則訪問對應閉包保存的i值便可。
for(var i = 0; i < 5; i++) {
console.log('test');
(function(){
setTimeout(function() {
console.log(i);
}, 0);
})(i);
}
//www.jianshu.com/p/cd3fee40e…web
六、下面兩個函數的返回值是同樣的嗎?爲何?apache
function foo1()
{
return {
bar: "hello"
};
}編程
function foo2()
{
return
{
bar: "hello"
};
}
foo1輸出:object {bar:'hello'};
foo2: undefined;
在編程語言中,基本都是使用分號(;)將語句分隔開,這能夠增長代碼的可讀性和整潔性。而在JS中,如若語句各佔獨立一行,一般能夠省略語句間的分號(;),JS 解析器會根據可否正常編譯來決定是否自動填充分號:
var test = 1 +
2
console.log(test); //3
等同於:var test=1+2;
console.log(test)//3
在上述狀況下,爲了正確解析代碼,就不會自動填充分號了,可是對於 return 、break、continue 等語句,若是後面緊跟換行,解析器必定會自動在後面填充分號(;);
七、console.log(1+ +"2"); 等同於:console.log(1+(+'2'));
+'2' 的 + 是一元操做符,對 '2' 進行Number()操做,轉爲數字的2,因此等於3;
除了加法運算符有可能把運算子轉爲字符串,其餘運算符都會把兩側的運算子自動轉成數值。
自動轉換類型:javascript.ruanyifeng.com/grammar/con…
八、
console.log(0.1 + 0.2);//0.30000000000000004
console.log(0.1 + 0.2 == 0.3);//false
計算機將全部數據以二進制的形式存儲的,
把0.1和0.2轉換成二進制:
0.1 => 0.0001 1001 1001 1001…(無限循環)
0.2 => 0.0011 0011 0011 0011…(無限循環)
可是計算機只能用有限的位數來存一個數,因此最終,計算機存的數是一個近似於 0.1 的小數。
因此當咱們計算 0.1 + 0.2 時,實際上算的是兩個近似值相加,獲得的值固然也是近似等於 0.3。
好比1/2,1/8,1/1024,這種2的倍數的能夠精確的轉換。
九、實現函數 isInteger(x) 來判斷 x 是不是整數
能夠將 x 轉換成10進制,判斷和自己是否是相等便可:
function isInteger(x) {
return parseInt(x, 10) === x;
}
ES6 對數值進行了擴展,提供了靜態方法 isInteger() 來判斷參數是不是整數:
十、(function() {
console.log(1);
setTimeout(function(){console.log(2)}, 1000);
setTimeout(function(){console.log(3)}, 0);
console.log(4);
})();
輸出內容是:1,4,3,2
JavaScript是單線程,單線程就意味着,全部任務須要排隊,前一個任務結束,纔會執行後一個任務。若是前一個任務耗時很長,後一個任務就不得不一直等着。js中全部任務能夠分紅兩種,一種是同步任務(synchronous),另外一種是異步任務(asynchronous)。同步任務指的是,在主線程上排隊執行的任務,只有前一個任務執行完畢,才能執行後一個任務;異步任務指的是,不進入主線程、而進入"任務隊列"(task queue)的任務,只有"任務隊列"通知主線程,某個異步任務能夠執行了,該任務纔會進入主線程執行。
異步執行的運行機制以下。(同步執行也是如此,由於它能夠被視爲沒有異步任務的異步執行。)
(1)全部同步任務都在主線程上執行,造成一個執行棧(execution context stack)。
(2)主線程以外,還存在一個"任務隊列"(task queue)。只要異步任務有了運行結果,就在"任務隊列"之中放置一個事件。
(3)一旦"執行棧"中的全部同步任務執行完畢,系統就會讀取"任務隊列",看看裏面有哪些事件。那些對應的異步任務,因而結束等待狀態,進入執行棧,開始執行。
(4)主線程不斷重複上面的第三步。
執行棧中的代碼(同步任務),老是在讀取"任務隊列"(異步任務)以前執行。
js 事件運行機制:www.ruanyifeng.com/blog/2014/1…
十一、寫一個少於80 字符的函數,判斷一個字符串是否是迴文字符串
function isPalindrome(str) {
return (str == str.split('').reverse().join(''));
}
//split() 方法用於把一個字符串分割成字符串數組。
//reverse() 方法用於顛倒數組中元素的順序。
//join() 方法用於把數組中的全部元素放入一個字符串。元素是經過指定的分隔符進行分隔的。
十二、
for (var i = 0; i < 5; i++) {
var btn = document.createElement('button');
btn.appendChild(document.createTextNode('Button ' + i));
(function(i){
btn.addEventListener('click', function(){ console.log(i); });
})(i);複製代碼
document.body.appendChild(btn);
}
1三、下面的代碼會輸出什麼?爲何?
console.log(1 + "2" + "2");//122
console.log(1 + +"2" + "2");//32
console.log(1 + -"1" + "2");//02
console.log(+"1" + "1" + "2");//112
console.log( "A" - "B" + "2");//NaN2
console.log( "A" - "B" + 2);//NaN
1四、下面的代碼會輸出什麼?爲何?
var arr1 = "john".split(''); //j o h n
var arr2 = arr1.reverse(); //n h o j
var arr3 = "jones".split(''); //j o n e s
var arr4 = arr2.push(arr3);
console.log(arr1);//["n", "h", "o", "j", Array[5]]
console.log(arr2);//["n", "h", "o", "j", Array[5]]
console.log(arr4);//5
這個徹底作錯了。
第一個錯誤:直接把arr3的數組信息逐個加在了arr2後,[n,h,o,j,j,o,n,e,s];
第二個錯誤,認爲arr1的值是[j,o,h,n];
第三個錯誤,arr4應該等於arr2 push 後的值;
第一個錯誤就不說了,弱智錯誤,
第二個錯誤,
JS中沒有指針,只有傳值(value)與傳址(reference引用)的區別,數組對數組是引用類型,數組對變量是值類型
var a = [1,2,3,4] //a不只是數組,仍是個對象,實際上a就是對[1,2,3,4]的引用
var b=a
var c=a
//以上兩條賦值語句創建了b與c 對a即[1,2,3,4]的引用,不管改變a 仍是b抑或c 都是對[1,2,3,4]的操做,這就是傳址(堆中操做)
var d=a[1] //則是把a[1]的值"1"傳遞給d,對d的改變則不會影響a[1],即所謂的傳值(棧中操做)
第三個錯誤,
unshift() 方法可向數組的開頭添加一個或更多元素,並返回新的長度。
push() 方法可向數組的末尾添加一個或多個元素,並返回新的長度。
pop() 方法用於刪除並返回數組的最後一個元素。
shift() 方法用於把數組的第一個元素從其中刪除,並返回第一個元素的值。
參考:www.cnblogs.com/bydclouds/p…
1五、var a={},
b={key:'b'},
c={key:'c'};
a[b]=123;
a[c]=456; 複製代碼
console.log(a[b]); //456
a的屬性名須要字符串,可是b和c是對象。所以,key值轉化字符串,調用了toString()方法,因此,實際的效果:
a["[object Object]"] = 123;
a["[object Object]"] = 456;
16 原型,原型鏈,做用域,做用域鏈
原型:函數都有一個原型屬性prototype,注:這個prototype的屬性值是一個對象,默認的有一個constructor的屬性,指向這個函數自己。對象有一個隱藏屬性proto,該實例對象的proto屬性指向原型對象prototype.
原型鏈:查找一個對象屬性時,先查找基本屬性,若沒有,則沿着proto這條鏈向上找,這就是原型鏈。
做用域(scope):已聲明變量或者函數的生命週期和做用範圍。
做用域鏈:當查找一個變量時,先從當前做用域尋找,若找不到,就會去定義當前做用域的函數做用域範圍內尋找,若找不到會一直查找到全局做用域,全局做用域都沒有找到,就真的沒有啦。
上下文執行環境:
1七、什麼是閉包?舉例說明
有兩種應用狀況:
一是:函數做爲返回值,
function fn(){
var max=10;
return function(x){
if(x>max){
console.log(x);
}
}
}
var f1=fn();
f1(15);
二是:函數做爲參數被傳遞:
var max=10;
fn=function(x){
if(x>max){
console.log(x);
}
};
(function(f){
var max=100;
f(15);
})(fn);
fn函數做爲一個參數被傳遞到另外一個函數,複製給f參數。執行f(15)時,max 變量的取值是10,而不是100.
1八、類
1九、Null 和Undefined的區別
Undefined是表明聲明未賦值的變量,變量的默認值是undefined;
Null是不存在的對象。
typeOf undefined=Undefined typeOf null=Object;
20、apply,call的區別???
apply,call的做用都是:繼承另一個對象的屬性.
2一、優化下面代碼:
var str="我喜歡我可愛的女友,";
str=str+"她叫喵喵,";
str=str+"她時而可愛,時而認真,";
str=str+"她那天真的笑聲可讓人忘掉一切煩惱。";
console.log(str);
優化後的:
var arr=[];
arr.push(‘我喜歡我可愛的女友,’);
arr.push(‘她叫喵喵,’);
arr.push(‘她時而可愛,時而認真,’);
arr.push(‘她那天真的笑聲可讓人忘掉一切煩惱。’);
console.log(arr.join(‘’));
2二、get和post 請求的區別。
一、get請求的數據會附在URL後,post 請求是放在HTTP header中一塊兒傳送到URL請求,用戶是看不到的;
二、Get請求大小有限制,Post 的數據量比較大,默認沒有限制。
三、get 請求和post 表達的語義不同,get是用於信息獲取,並且應該是安全的和冪等的,固然這裏的安全指的是用於獲取數據而非是修改數據,所以除了返回結果不會產生其餘的反作用,並且絕大部分的get請求都直接被CDN緩存了,大大減小服務器的負擔。post是讀取修改信息,非冪等的,會產生反作用,因此必須交由web服務器處理。
四、get請求的URL能夠被手動修改,請求的URL是能夠被搜索引擎收錄的,請求的URL能夠存在書籤裏,或者歷史裏,或者分享給別人。
2三、爲何學習NodeJS ?koa,hapi比較?
一、node的是基於google瀏覽器的v8引擎,保證了NOdeJS的性能和穩定性。二、NodeJS 的開發很是的高效,並且代碼簡單,並且NodeJS是異步編程,讓Nodejs處理IO密集型應用有了明顯的優點。三、NodeJS的社區很壯大,不只包的數量在快速增長,包的質量也明顯好於其餘語言。
不適合的領域:一、計算密集型的應用 二、大內存的應用,因爲V8引擎有內存設計的限制。32位環境中最大是1G,64位的環境最大是2G,若是一次讀入10G數據對於NodeJS來講也是沒法實現的。三、靜態服務器,雖然Node的優點在於IO密集處理,可是和nginx的處理靜態資源仍是有很大的差距的。
2四、關於先後端分離的理解。
2五、瀏覽器的生成頁面操做???
一、加載HTML:用戶輸入域名,瀏覽器根據域名進行URL解析,向服務器發送請求,服務器返回HTML文件。
二、解析HTML:從HTML解析出DOM tree,CSS 規則樹,
三、渲染:根據Dom樹和css 規則樹構建一個渲染樹,rendering tree,
四、繪製:遍歷DOM 樹,繪製節點。
迴流:當操做DOM,某個部分影響佈局,就須要去從新渲染頁面。
重繪:改變DOM的背景顏色,字體顏色等,不影響元素周圍或內部的屬性,將引發瀏覽器的重繪,
前端渲染的優勢:
一、減小服務器的資源
二、富交互
三、局部刷新
四、懶加載
五、一次編碼多端執行
缺點呢:
一、不利於SEO
二、增長請求次數,渲染頁面慢
方法:
一、渲染頁面加一下loading效果。
二、部分同構;指先後端共用 JS,首次渲染時使用 Node.js 來輸出 HTML
2五、虛擬DOM
虛擬DOM 的核心思想是最小化操做DOM,使執行效率獲得保證。
DOM很慢,而javascript對象處理很快。這樣咱們用javascript對象表示DOM信息和結構,當狀態變動的時候,從新渲染javascript的對象結構。
用新的樹和舊的樹作對比,記錄兩棵樹的差別。記錄下來的不一樣就是咱們須要對頁面真正DOM操做,而後把他們應用在DOM樹上,頁面就變動了。這樣就能夠作到:視圖的結構確實是整個全新渲染了,可是最後操做DOM的時候至少變動了不一樣的地方
CSS 部分
一、CSS樣式的優先級
(1)相同權值狀況下,CSS樣式的優先級就是就近原則。!important>內聯樣式>內嵌樣式>外鏈樣式
(2)全職不一樣是,根據權值來判斷,標籤的權值是1,類的權值是10,ID的權值是100;
(3)若使用 js 修改,行間樣式box.style.background = "red"; > box.className = ("blue");
二、css display屬性有哪些值,各有什麼表現;
none:元素隱藏,並且元素顯示的空間也不會保留,屬性visibility:hidden是保留元素的空間的;
block:將元素設置爲塊級元素,元素單獨佔一行,能夠設置width和height了。
inline:將元素設置爲行內元素,元素先後沒有換行符。並且沒法設置寬高
inline-block:行內塊元素。這個屬性值融合了inline 和 block 的特性,便是它既是內聯元素,又能夠設置width和height。
inherit: 規定應該從父元素繼承 display 屬性的值。
table: 此元素會做爲塊級表格來顯示(相似
一、網站性能優化 (1)減小一個頁面訪問所產生的http鏈接次數; 儘可能合併js和css文件,減小獨立文件個數;可使用雪碧圖 減小圖片的數量 (2)將CSS放在頁面頂端,JS文件放在頁面底端 CSS的引用要放在html的頭部header中,JS文件引用盡可能放在頁面底端標籤的後面,主要的思路是讓核心的頁面內容儘早顯示出來。不過要注意,一些大量使用js的頁面,可能有一些js文件放在底端會引發一些難以預料的問題,根據實際狀況適當運用便可; (3)使JS,CSS文件內容最小化 使用一些javascript壓縮工具對js腳本進行壓縮,去除其中的空白字符、註釋,最小化變量名等。 (4)儘可能減小外部腳本的使用,減小DNS查詢時間 不要在網頁中引用太多的外部腳本,首先,一次dns的解析過程會消耗20-120毫秒的時間;其次,若是在頁面中引用太多的外部文件(如各類廣告、聯盟等代碼),可能會由於外部文件的響應速度而將你的網站拖得很慢。若是不得不用,那麼就儘可能將這些腳本放在頁腳吧。不過有一點須要說起,就是瀏覽器通常只能並行處理同一域名下的兩個請求,而對於不一樣子的域名則不受此限制,所以適當將本站靜態內容(css,js)放在其餘的子域名下(如 static.xxx.com)會有利於提升瀏覽器並行下載網頁內容的能力。 (5)最大限度利用用戶瀏覽器的cache來減小服務器的開銷。 必需要了解瀏覽器訪問url時的工做機制: a. 第一次訪問url時,用戶從服務器端獲取頁面內容,並把相關的文件(images,css,js…)放在高速緩存中,也會把文件頭中的expired time,last modified, Tags等相關信息也一同保留下來。 b. 用戶重複訪問url時,瀏覽器首先看高速緩存中是否有本站同名的文件,若是有,則檢查文件的過時時間;若是還沒有過時,則直接從緩存中讀取文件,再也不訪問服務器。 c. 若是緩存中文件的過時時間不存在或已超出,則瀏覽器會訪問服務器獲取文件的頭信息,檢查last modifed和ETags等信息,若是發現本地緩存中的文件在上次訪問後沒被修改,則使用本地緩存中的文件;若是修改過,則從服務器上獲取最新版本。 (6)動靜分離。apache是一個功能完善但比較龐大的web server,它的資源佔用基本上和同時運行的進程數呈正比,對服務器內存的消耗比較大,處理並行任務的效率也通常。在一些狀況下,咱們能夠動靜分離