JavaScript 有哪些數據類型javascript
原始數據類型:php
Boolean: 布爾表示一個邏輯實體,能夠有兩個值:true 和 falsecss
Number: 用於表示數字類型html
String: 用於表示文本數據前端
Null: Null 類型只有一個值: null,特指對象的值未設置vue
Undefined: 一個沒有被賦值的變量會有個默認值 undefinedhtml5
Symbol: 符號(Symbols)是ECMAScript第6版新定義的。符號類型是惟一的而且是不可修改的java
引用類型:Objectnode
介紹一下 JS 有哪些內置對象jquery
Object 是 JavaScript 中全部對象的父對象
數據封裝類對象:Object、Array、Boolean、Number、String
其餘對象:Function、Argument、Math、Date、RegExp、Error
講講JS的語言特性
JavaScript腳本語言具備如下特色:
腳本語言
JavaScript是一種解釋型的腳本語言,C、C++等語言先編譯後執行,而JavaScript是在程序的運行過程當中逐行進行解釋。
基於對象
JavaScript是一種基於對象的腳本語言,它不只能夠建立對象,也能使用現有的對象。
簡單
JavaScript語言中採用的是弱類型的變量類型,對使用的數據類型未作出嚴格的要求,是基於Java基本語句和控制的腳本語言,其設計簡單緊湊。
動態性
JavaScript是一種採用事件驅動的腳本語言,它不須要通過Web服務器就能夠對用戶的輸入作出響應。在訪問一個網頁時,鼠標在網頁中進行鼠標點擊或上下移、窗口移動等操做JavaScript均可直接對這些事件給出相應的響應。
跨平臺性
JavaScript腳本語言不依賴於操做系統,僅須要瀏覽器的支持。所以一個JavaScript腳本在編寫後能夠帶到任意機器上使用,前提上機器上的瀏覽器支 持JavaScript腳本語言,目前JavaScript已被大多數的瀏覽器所支持。不一樣於服務器端腳本語言,例如PHP與ASP,JavaScript主要被做爲客戶端腳本語言在用戶的瀏覽器上運行,不須要服務器的支持。因此在早期程序員比較青睞於JavaScript以減小對服務器的負擔,而與此同時也帶來另外一個問題:安全性。而隨着服務器的強壯,雖然程序員更喜歡運行於服務端的腳本以保證安全,但JavaScript仍然以其跨平臺、容易上手等優點大行其道。同時,有些特殊功能(如AJAX)必須依賴Javascript在客戶端進行支持。隨着引擎如V8和框架如Node.js的發展,及其事件驅動及異步IO等特性,JavaScript逐漸被用來編寫服務器端程序。
JS數組有哪些經常使用方法?
https://cloud.tencent.com/developer/article/1333188
修改方法(原數組改變):
pop(): 刪除數組的最後一個元素,並返回這個元素
push():在數組的末尾增長一個或多個元素,並返回數組的新長度
shift(): 刪除數組的第一個元素,並返回這個元素
unshift(): 在數組的開頭增長一個或多個元素,並返回數組的新長度
splice(): 在任意的位置給數組添加或刪除任意個元素
(輸入:第一個參數爲指定插入或刪除的起始位置,第二個參數爲要刪除的個數。以後的參數表示須要插入到數組中的元素)
(輸出:返回一個由刪除元素組成的數組。)
reverse(): 顛倒數組中元素的排列順序
(輸入:無)
(輸出:逆序的數組)
sort(): 對數組元素進行排序,並返回當前數組
(輸入:比較函數或null。null時表示按照字母表順序排序;傳入帶兩個參數的比較函數時;第一個參數在前,則返回小於0的數值;第一個參數在後,則返回大於0的數組 )
(輸出:排序後數組 )
訪問方法:
slice(): 抽取當前數組中的一段元素組合成一個新數組
(輸入:片斷的開始和結束 )
(輸出:返回的數組包含第一個參數指定的位置和全部到但不含第二個參數指定位置之間的全部元素。若是爲負數,表示相對於數組中最後一個元素的位置。)
concat(): 將當前數組和其它若干個數組或者若干個非數組值組合成的新數組
(輸入:待拼接的元素;若是參數中有數組,則鏈接的是數組元素,而非數組自己;可是不支持遞歸,不修改調用的數組。)
(輸出:拼接後的新數組)
join(): 將數組中全部元素都轉化爲字符串並鏈接在一塊兒。
(輸入: 分隔符,默認爲逗號)
(輸出:分隔符分割的字符串)
indeOf(): 返回數組中第一個與指定值相等的元素的索引,若是找不到這樣的元素,則返回 -1
lastIndexOf(): 返回數組中最後一個(從右邊數第一個)與指定值相等的元素的索引,若是找不到這樣的元素,則返回 -1
toString()/toLocalString():將數組的每一個元素轉化爲字符串,而且輸入用逗號分隔的字符串列表。功能相似join();
迭代方法:
forEach(): 從頭到尾遍歷數組,爲每一個元素調用指定函數
(輸入:輸入爲一個待遍歷函數,函數的參數依次爲:數組元素、元素的索引、數組自己)
(輸出:只是執行了遍歷函數,無特定返回)
map(): 調用的數組的每個元素傳遞給指定的函數,並返回一個新數組
(輸入:輸入爲一個待遍歷函數,函數的參數依次爲:數組元素、元素的索引、數組自己)
(輸出:執行完函數的新數組)
filter(): 將全部在過濾函數中返回 true 的數組元素放進一個新數組中並返回
every(): 若是數組中的每一個元素都知足測試函數,則返回 true,不然返回 false
some(): 若是數組中至少有一個元素知足測試函數,則返回 true,不然返回 false
JS字符串有哪些經常使用方法?
http://www.javashuo.com/article/p-rfoifhvi-c.html
截取字符串方法:
slice() 提取字符串的某個部分,並以新的字符串返回被提取的部分。
split() 用於把一個字符串分割成字符串數組。
substr() 方法可在字符串中抽取從 start 下標開始的指定數目的字符。
substring() 方法用於提取字符串中介於兩個指定下標之間的字符。
其餘方法:
charAt() 返回指定位置的字符。
charCodeAt() 返回在指定的位置的字符的 Unicode 編碼。
concat() 用於鏈接兩個或多個字符串。
indexOf() 方法 返回指定字符串在字符串中首次出現的位置。匹配不到則返回-1。
lastIndexOf() 返回指定字符串值最後出現的位置,在一個字符串中的指定位置從後向前搜索。
replace() 用於在字符串中用一些字符替換另外一些字符,或替換一個與正則表達式匹配的子串。
trim() 去除 str 開頭和結尾處的空白字符,返回 str 的一個副本,不影響字符串自己的值
toLocaleUpperCase() / toLocaleLowerCase() 用於字符串轉換大小寫(與下面的方法方法僅在某些外國小語種有差異)
match() 在字符串內檢索指定的值,或找到一個或多個正則表達式的匹配。匹配不到返回Null。
search() 用於檢索字符串中指定的子字符串,或檢索與正則表達式相匹配的子字符串。無匹配返回-1。
fromCharCode() 接受一個指定的 Unicode 值,而後返回一個字符串。
substr()和 substring()有什麼區別?
什麼是命令式編程?什麼是聲明式編程?
https://www.jianshu.com/p/7316e3288fd0
- 命令式編程:命令「機器」如何去作事情(how),這樣無論你想要的是什麼(what),它都會按照你的命令實現。
- 聲明式編程:告訴「機器」你想要的是什麼(what),讓機器想出如何去作(how)。
例:將一個數組的每一個值乘2;
命令式:
var numbers = [1,2,3,4,5] var doubled = [] for(var i = 0; i < numbers.length; i++) { var newNumber = numbers[i] * 2 doubled.push (newNumber) } console.log (doubled)
聲明式:
var numbers = [1,2,3,4,5] var doubled = numbers.map (function (n) { return n * 2 }) console.log (doubled)
什麼是面向對象編程?
https://baike.baidu.com/item/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/24792?fromtitle=%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%BC%96%E7%A8%8B&fromid=254878&fr=aladdin
面向對象程序設計(英語:Object-oriented
programming,縮寫:OOP)是種具備對象概念的程序編程範型,同時也是一種程序開發的方法。它可能包含數據、屬性、代碼與方法。對象則指的是類的實例。它將對象做爲程序的基本單元,將程序和數據封裝其中,以提升軟件的重用性、靈活性和擴展性,對象裏的程序能夠訪問及常常修改對象相關連的數據。在面向對象程序編程裏,計算機程序會被設計成彼此相關的對象。
面向對象主要特徵:封裝性、繼承性、多態性
面向對象編程具備如下優勢:
易維護
採用面向對象思想設計的結構,可讀性高,因爲繼承的存在,即便改變需求,那麼維護也只是在局部模塊,因此維護起來是很是方便和較低成本的。
易擴展
經過繼承,咱們能夠大幅減小多餘的代碼,並擴展示有代碼的用途;
咱們能夠在標準的模塊上(這裏所謂的」標準」指程序員之間彼此達成的協議)構建咱們的程序,而沒必要一切從頭開始。這能夠減小軟件開發時間並提升生產效率;
模塊化
封裝能夠定義對象的屬性和方法的訪問級別,經過不一樣的訪問修飾符對外暴露安全的接口,防止內部數據在不安全的狀況下被修改。這樣能夠使程序具有更高的模塊化程度,方便後期的維護和修改。
同時,面嚮對象語言容許一個對象的多個實例同時存在,並且彼此之間不會相互干擾;
方便建模
雖然面嚮對象語言中的對象與現實生活中的對象並非同個概念,但不少時候,每每能夠使用現實生活中對象的概念抽象後稍做修改來進行建模,這大大方便了建模的過程。(但直接使用現實中的對象來建模有時會拔苗助長)。
JS判斷數據類型的各類方法?
http://www.javashuo.com/article/p-svojmnaq-g.html
①typeof
typeof是一個運算符,它返回一個用來表示表達式的數據類型的字符串。
語法:typeof(表達式)和typeof 變量名,第一種是對錶達式作運算,第二種是對變量作運算。語法中的圓括號是可選項
typeof的運算數未定義,返回的就是 「undefined」.
運算數爲數字 typeof(x) = 「number」
字符串 typeof(x) = 「string」
布爾值 typeof(x) = 「boolean」
對象,數組和null typeof(x) = 「object」
函數 typeof(x) = 「function」
特殊狀況:
- 對於基本類型,除 null 之外,都可以返回正確的結果。
- 對於引用類型,除 function 之外,一概返回 object 類型。
- 對於s型。
- 對於 function 返回 function 類型。
②instanceof
instanceof運算符用來判斷一個構造函數的prototype屬性所指向的對象是否存在另一個要檢測對象的原型鏈上。一般來說,使用 instanceof 就是判斷一個實例是否屬於某種類型。
語法:obj instanceof Object;//true
③constructor
constructor 屬性返回對建立此對象的數組函數的引用。
語法:object.constructor
細節問題:
- null和undefined是無效的對象,所以是不會有constructor存在的,這兩種類型的數據須要經過typeof來判斷。
- JS對象的constructor是不穩定的,這個主要體如今自定義對象上,當開發者重寫prototype後,原有的constructor會丟失,constructor會默認爲Object

爲何變成了Object?
prototype被從新賦值的是一個{}, {}是new Object()的字面量,所以new Object()會將Object原型上的constructor傳遞給{},也就是Object自己。
所以,爲了規範,在重寫對象原型時通常都須要從新給constructor賦值,以保證明例對象的類型不被改寫。
④Object.prototype.toString.call
toString是Object原型對象上的一個方法,該方法默認返回其調用者的具體類型,更嚴格的講,是 toString運行時this指向的對象類型。
返回的類型格式爲[object,xxx],xxx是具體的數據類型,其中包括:String,Number,Boolean,Undefined,Null,Function,Date,Array,RegExp,Error,HTMLDocument,... 基本上全部對象的類型均可以經過這個方法獲取到。
須要注意的是,必須經過Object.prototype.toString.call來獲取,而不能直接 new Date().toString(), 從原型鏈的角度講,全部對象的原型鏈最終都指向了Object, 按照JS變量查找規則,其餘對象應該也能夠直接訪問到Object的toString方法,而事實上,大部分的對象都實現了自身的toString方法,這樣就可能會致使Object的toString被終止查找,所以要用call來強制執行Object的toString方法。
⑤jquery.type()
jQuery.type() === "undefined"
jQuery.type( /test/ ) ===
"regexp"
源碼分析:
var class2type = {};
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase();
});
type: function( obj ) {
// 當obj爲undefined或null時,直接返回對應的字符串形式
if ( obj == null ) {
return obj + "";
}
// Support: Safari <= 5.1 (functionish RegExp)
// 當obj的類型爲object或function時,執行class2type[ toString.call(obj) ]
// 若是是本身建立了數據類型的話,那麼就會統一返回"object"
// 不然執行 typeof obj
return typeof obj === "object" || typeof obj === "function" ?
class2type[ toString.call(obj) ] || "object" :
typeof obj;
},
undefined 和 null 有什麼區別
http://www.ruanyifeng.com/blog/2014/03/undefined-vs-null.html
javaScript權威指南: null 和 undefined 都表示「值的空缺」,你能夠認爲undefined是表示系統級的、出乎意料的或相似錯誤的值的空缺,而null是表示程序級的、正常的或在乎料之中的值的空缺。
null表示表明「空值」,表明一個空對象指針
null的典型用法:
做爲函數的參數,表示該函數的參數不是對象
做爲對象原型鏈的終點
undefined表示"缺乏值",就是此處應該有一個值,可是尚未定義
undefined的典型用法:
變量被聲明瞭,但沒有賦值時,就等於undefined
調用函數時,應該提供的參數沒有提供,該參數等於undefined
對象沒有賦值的屬性,該屬性的值爲undefined
函數沒有返回值時,默認返回undefined
請指出document load和document ready的區別?
https://zhidao.baidu.com/question/432820456183363324.html
DOM文檔加載的步驟:
(1) 解析HTML結構。
(2) 加載外部腳本和樣式表文件。
(3) 解析並執行腳本代碼。
(4) 構造HTML DOM模型。
(5) 加載圖片等外部文件。
(6) 頁面加載完畢。
load:是當頁面全部資源所有加載完成後(包括DOM文檔樹,css文件,js文件,圖片資源等),執行一個函數
問題:若是圖片資源較多,加載時間較長,onload後等待執行的函數須要等待較長時間,因此一些效果可能受到影響
$(document).ready():是當DOM文檔樹加載完成後執行一個函數 (不包含圖片,css等)因此會比load較快執行
在原生的jS中不包括ready()這個方法,只有load方法就是onload事件
Js 有哪些建立對象的方式?
http://www.javashuo.com/article/p-nybgevtd-p.html
https://blog.csdn.net/zpcqdkf/article/details/80401999
①使用字面量{}
②構造函數方式建立new Object()
④工廠模式:
function createPerson(name, age) {
var o = new Object()
o.name = name;
o.age = age;
o.sayName = function() {
console.log(name)
}
return o;
}
var p1 = createPerson(...);
不足:每次經過Person建立對象的時候,全部的say方法都是同樣的,可是卻存儲了屢次,浪費資源
⑤構造函數模式(constructor):
function Person(name, age) {
http://www.javashuo.com/tag/this.name = name
this.age = age
this.sayName = function() {
console.log(name)
}
}
var p1 = new Person(...);
與工廠模型相比,具備如下特色:
1.沒有顯示建立對象;
2.直接將屬性和方法賦給了this對象;
3.沒有return語句;
4.要建立新實例,必須使用new操做符;(不然屬性和方法將會被添加到window對象)
5.能夠使用instanceof操做符檢測對象類型
不足:
構造函數模式隱試的在最後返回return this 因此在缺乏new的狀況下,會將屬性和方法添加給全局對象,瀏覽器端就會添加給window對象,能夠根據return this 的特性調用call或者apply指定this
構造函數內部的方法會被重複建立,不一樣實例內的同名函數是不相等的。可經過將方法移到構造函數外部解決這一問題,但面臨新問題:封裝性很差。
⑥原型模式(prototype):
function Person() {};
Person.prototype = {
name: 'xiaoming',
friend: ['xiaoli'],
sayName: function () {
aleri(this.name);
}
}
var p1 = new Person();
console.log(p1 instanceof Person); //true
console.log(p1.prototype.constructor); //Object
console.log(p1.constructor); //Object
p1.constructor再也不指向Person,而是指向了Object。若是constructor很重要,則須要特地將其設爲適當的值,如:
Person.prototype = {
constructor: Person,
name: 'xiaoming',
friend: ['xiaoli','xiaohong'],
sayName: function () {
aleri(this.name);
}
}
可是這種方式會致使constructor屬性變成可枚舉。
若是想設置爲不可枚舉的(默認不可枚舉),能夠使用Object.defineProperty(Person.prototype, 「constructor」, {
enumerable: false,
value: Person
});
特色:實現了方法與屬性的共享,能夠動態添加對象的屬性和方法。
不足:
1.對於包含基本值的屬性能夠經過在實例上添加一個同名屬性隱藏原型中的屬性。而後,對於包含引用數據類型的值來講,會致使問題;
2.沒有辦法建立實例本身的屬性和方法,也沒有辦法傳遞參數。
⑦構造函數+原型模式:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype = {
constructor: Person,
sayName: function () {
aleri(this.name);
}
}
特色:構造函數模式用於定義實例屬性,而原型模式用於定義方法和共享的屬性。
⑧動態原型模式:
function Person (name, age) {
this.name = name;
this.age = age;
if(typeof this.sayName != 'function') {
Person.prototype.sayName = function () {
alert(this.name);
};
};
}
特色:在第一次調用構造函數時,將方法賦給原型對象的相應屬性,其餘示例的處理方式同構造函數模式;
⑨Object.create()
⑩寄生構造函數模式:
特色:僅僅封裝建立對象的代碼,而後再返回新建立的對象,仍使用new
操做符調用;
穩妥構造函數模式:
特色:沒有公共屬性,只有私有變量和方法,以及一些get/set
方法,用以處理私有變量。
new一個對象經歷了哪些步驟?
要建立person的實例,必須使用new操做符,以這種方式調用構造函數會經歷4個步驟:
一、建立一個新對象
二、將構造函數的做用域(this)賦給新對象
三、執行構造函數中的代碼
四、返回新對象
對 this 的理解?
http://www.ruanyifeng.com/blog/2018/06/javascript-this.html
this爲做用域上下文
通常狀況下函數執行時,this老是指向調用該函數的對象。
當使用箭頭函數的時候,狀況就有所不一樣了:箭頭函數內部的 this 是詞法做用域,由上下文肯定。
使用場景:
①在全局環境中,this 永遠指向 window。
普通函數在調用時候(注意不是構造函數,前面不加 new),其中的 this 也是指向 window
匿名函數中的this指向全局對象window
setInterval和setTimeout定時器中的this指向全局對象window
②構造函數:若是函數做爲構造函數使用,那麼其中的 this 就表明它即將 new 出來的對象。
③方法調用:若是函數做爲對象的方法時,方法中的 this 指向該對象。
④構造函數 prototype 屬性:在整個原型鏈中,this 表明的也是當前對象的值。
⑤call/apply/bind調用:當一個函數被 call、apply 或者 bind 調用時,this 的值就取傳入的對象的值。
⑥DOM綁定事件:在一個 HTML DOM 事件處理程序裏,this 始終指向這個處理程序所綁定的 HTML DOM 節點
⑦箭頭函數:當使用箭頭函數的時候,狀況就有所不一樣了:箭頭函數內部的 this 是詞法做用域。
函數執行時,this老是指向調用該函數的對象(即:判斷this所在的函數屬於誰)。
apply()、call()和 bind() 的區別及使用?
http://www.javashuo.com/article/p-optnjegs-hn.html
三者的相同點:都是用來改變this的指向
call 和 apply 的主要做用,是改變對象的執行上下文,而且是當即執行的。它們在參數上的寫法略有區別。
call 的語法:
Function.call(obj,[param1[,param2[,…[,paramN]]]])
注意點:
- 調用 call 的對象,必須是個函數 Function。
- call 的第一個參數,是一個對象。 Function 的調用者,將會指向這個對象。若是不傳,則默認爲全局對象 window。
- 第二個參數開始,能夠接收任意個參數。每一個參數會映射到相應位置的 Function 的參數上。可是若是將全部的參數做爲數組傳入,它們會做爲一個總體映射到 Function 對應的第一個參數上,以後參數都爲空。
apply 的語法:
Function.apply(obj[,argArray])
注意點:
- 調用 apply 的對象,必須是個函數 Function。
- 第二個參數,必須是數組或者類數組,它們會被轉換成類數組,傳入 Function 中,而且會被映射到 Function 對應的參數上。這也是 call 和 apply 之間,很重要的一個區別。
bind 方法也能改變函數體內的 this 指向。不一樣的是,bind 方法的返回值是函數,而且須要稍後調用,纔會執行。而 apply 和 call 則是當即調用。
bind語法:
Function.bind(thisArg[, arg1[, arg2[, ...]]])
使用場景:
call
對象的繼承
判斷數據類型
Object.prototype.toString.call();
將類數組變爲數組
Array.prototype.slice.call(arguments);
apply
求數組最大值
let max = Math.max.apply(null, array);
實現兩個數組合並
let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; Array.prototype.push.apply(arr1, arr2);
new 操做符具體幹了什麼
https://cloud.tencent.com/developer/article/1195936?from=10680
https://www.jianshu.com/p/e7015984f608
https://www.jianshu.com/p/db4ae33d1e53
先看代碼
var Func = function(){ };
var func = new Func ();
new共通過了4幾個階段
一、建立一個空對象
var obj = new Object();
二、設置原型鏈,將新建立對象(obj)的__proto__指向構造函數的原型
obj.__proto__ = Func.prototype;
三、讓構造函數中的this指向新建立對象(obj),傳入構造函數的參數並執行Func的函數體。
var result = Func.apply(obj,arguments);
四、判斷Func的返回值類型:
若是是值類型,返回obj。若是是引用類型,就返回這個引用類型的對象。
能夠看出new省略了哪幾步:
1.不用手動新建一個obj ,new會幫你建立
2.new出來的實例的__proto__會指向構造函數的prototype。構造函數的方法,實例能夠直接調用。
3.構造函數this的做用域會指向實例自己。
4.不用手動return新建的obj,new會幫你return。
JS如何實現對對象的拷貝(淺拷貝與深拷貝)?
https://blog.csdn.net/yaodebian/article/details/82778403
JS中對象分爲基本類型和複合(引用)類型,基本類型存放在棧內存,複合(引用)類型存放在堆內存。
堆內存用於存放由new建立的對象,棧內存存放一些基本類型的變量和對象的引用變量。
- 淺拷貝:淺拷貝是拷貝引用,拷貝後的引用都是指向同一個對象的實例,彼此之間的操做會互相影響;
- 深拷貝:在堆中從新分配內存,而且把源對象全部屬性都進行新建拷貝,以保證深拷貝的對象的引用圖不包含任何原有對象或對象圖上的任何對象,拷貝後的對象與原來的對象是徹底隔離,互不影響;
淺拷貝分兩種狀況,一是直接拷貝源對象的引用,二是源對象拷貝實例,但其屬性(類型爲Object、Array的屬性)拷貝引用。
源對象拷貝實例,其屬性對象拷貝應用
這種狀況下,外層源對象是拷貝實例,若是其屬性元素爲複雜數據類型時,內層元素拷貝引用。
對於對象實例的拷貝,經常使用的方法有:Array.prototype.slice(), Array.prototype.concat(), jQuery的$.extend({},obj)和ES6中的拓展運算符(...)
例:
var a = [{c:1}, {d:2}];
var b = a.slice();
console.log(a === b);
a[0].c = 3;
console.log(b[0].c);
深拷貝方法:
①JSON.parse(JSON.stringify(目標對象); ( 即JSON.parse()和JSON.stringify() )
var a = {...};
var temp = JSON.stringify(a);
var b = JSON.parse(temp);
不足:只能拷貝符合JSON數據標準類型的對象,對於包含有function或者正則類型值解析時會報錯
②使用遞歸
var clone = function (obj) {
if (obj === null) return null;
if (typeof obj !=== 'object') return obj;
if (obj.custructor === Date) return new Date(obj);
var newObj = new obj.constructor(); // 保持繼承鏈
for (var key in obj) {
if (obj.hasOwnProperty(key)) { //不遍歷其原型鏈上的屬性
var val = obj[key];
//使用arguments.callee解除與函數名的耦合
newObj[key] = typeif val === 'object' ? arguments.callee(val) : val;
}
}
return newObj;
}
這裏有三點須要注意:
一、用new obj.constructor ()構造函數新建一個空的對象,而不是使用{}或者[],這樣能夠保持原形鏈的繼承;
二、用obj.hasOwnProperty(key)來判斷屬性是否來自原型鏈上,由於for..in..也會遍歷其原型鏈上的可枚舉屬性。
三、上面的函數用到遞歸算法,在函數有名字,並且名字之後也不會變的狀況下,這樣定義沒有問題。但問題是這個函數的執行與函數名 factorial 牢牢耦合在了一塊兒。爲了消除這種緊密耦合的現象,須要使用 arguments.callee。
③lodash —— _.cloneDeep()
很好地兼容了ES6的新引用類型,並且處理了環型對象的狀況
JS如何實現繼承?
http://www.php.cn/js-tutorial-411754.html
JS中的類型轉換規則?
https://cloud.tencent.com/developer/article/1186778
轉換爲字符型方法:
一、利用引號(「」)轉換爲字符型
二、利用函數String();轉換爲字符型 var num=10; console.log(String(num));//輸出爲字符型
布爾型:true和false
一、利用!!轉換爲布爾型 var num=20; console.log(!!num)
二、利用Boolean()轉換
三、var num="0"; num++; console.log(num);//1
var num="0"; num=num+1; console.logf(num);//01
轉換爲數值型
一、-、*、/能夠強制轉換
二、利用Number();
parseInt(10,2)//2(將10這個二進制轉換爲十進制數) parseInt(值,進制數)、parseFloat()
NAN,不是一個數字
什麼是閉包?
https://cloud.tencent.com/developer/article/1054445
https://cloud.tencent.com/developer/article/1390165
https://cloud.tencent.com/developer/article/1009285
https://cloud.tencent.com/developer/article/1407782
remember 詞法做用域的基礎規則:函數被執行時(executed)使用的做用域鏈(scope chain)是被定義時的scope chain,而不是執行時的scope chain
閉包:其實就是將函數內部和函數外部鏈接起來的一座橋樑,可讓函數外部的代碼訪問函數內容變量,能夠把閉包簡單理解成「定義在一個函數內部的函數」
function Person() {
var name = 'hello'
function say () {
console.log(name)
}
return say()
}
Person() // hello
因爲 JavaScript 特殊的做用域,函數外部沒法直接讀取內部的變量,內部能夠直接讀取外部的變量,從而就產生了閉包的概念
閉包有三個特性:
1.函數嵌套函數
2.函數內部能夠引用外部的參數和變量
3.參數和變量不會被垃圾回收機制回收
用途:
最大用處有兩個,一個是前面提到的能夠讀取函數內部的變量,另外一個就是讓這些變量的值始終保持在內存中。
使用場景:
閉包經典使用場景一:經過循環給頁面上多個dom節點綁定事件
閉包使用場景二:封裝變量和方法
閉包使用場景三:延續局部變量的壽命
閉包使用場景四:採用函數引用方式的setTimeout調用
閉包使用場景五:將函數關聯到對象的實例方法
注意點:
因爲閉包會使得函數中的變量都被保存在內存中,內存消耗很大,因此不能濫用閉包,不然會形成網頁的性能問題,在IE中可能致使內存泄露
介紹一下 JavaScript 原型?原型鏈?它們有何特色
(1)原型
首先明確一點,JavaScript是基於原型的
每一個構造函數(constructor)都有一個原型對象(prototype),原型對象都包含一個指向構造函數的指針,而實例(instance)都包含一個指向原型對象的內部指針。
(2)原型鏈
JavaScript中全部的對象都是由它的原型對象繼承而來。而原型對象自身也是一個對象,它也有本身的原型對象,這樣層層上溯,就造成了一個相似鏈表的結構,這就是原型鏈。
全部原型鏈的終點都是Object函數的prototype屬性。Objec.prototype指向的原型對象一樣擁有原型,不過它的原型是null,而null則沒有原型
1.JS中每一個函數都存在有一個原型對象屬性prototype。而且全部函數的默認原型都是Object的實例。
2.原型鏈,簡單理解就是原型組成的鏈,對象的__proto__是它的原型,而原型也是一個對象,也有__proto__屬性,原型的__proto__又是原型的原型,就這樣能夠一直經過__proto__想上找,這就是原型鏈,當向上找找到Object的原型的時候,這條原型鏈就算到頭了。

instanceof是判斷實例對象的__proto__和生成該實例的構造函數的prototype是否是引用的同一個地址。

3.原型鏈實現了繼承。原型鏈存在兩個問題:
(1)、包含引用類型值的原型屬性會被全部實例共享。
(2)、 在建立子類型時,沒法向超類型的構造函數中傳遞參數。
Ajax是什麼? 如何建立一個Ajax?
ajax的全稱:AsynchronousJavascript And XML。
異步傳輸+js+xml。
所謂異步,在這裏簡單地解釋就是:向服務器發送請求的時候,咱們沒必要等待結果,而是能夠同時作其餘的事情,等到有告終果它本身會根據設定進行後續操做,與此同時,頁面是不會發生整頁刷新的,提升了用戶體驗。
(1)建立XMLHttpRequest對象,也就是建立一個異步調用對象
(2)建立一個新的HTTP請求,並指定該HTTP請求的方法、URL及驗證信息
(3)設置響應HTTP請求狀態變化的函數
(4)發送HTTP請求
(5)獲取異步調用返回的數據
(6)使用JavaScript和DOM實現局部刷新
同步和異步的區別?怎麼異步加載 JavaScript?
(1)
同步:瀏覽器訪問服務器請求,用戶看獲得頁面刷新,從新發請求,等請求完,頁面刷新,新內容出現,用戶看到新內容,j進行下一步操做。
異步:瀏覽器訪問服務器請求,用戶正常操做,瀏覽器後端進行請求。等請求完,頁面不刷新,新內容也會出現,用戶看到新內容。
(2)
動態添加 script 標籤
defer
async
defer屬性和async都是屬於 script 標籤上面的屬性,二者都能實現 JavaScript 的異步加載。不一樣之處在於:async 在異步加載完成的時候就立刻開始執行了,defer 會等到 html 加載完畢以後再執行
什麼是內存泄漏?哪些操做會形成內存泄漏?
http://www.ruanyifeng.com/blog/2017/04/memory-leak.html
內存泄漏(Memory Leak)是指程序中己動態分配的堆內存因爲某種緣由程序未釋放或沒法釋放,形成系統內存的浪費,致使程序運行速度減慢甚至系統崩潰等嚴重後果。
內存泄漏:是指一塊被分配的內存既不能使用,又不能回收,直到瀏覽器進程結束
可能形成內存泄漏的操做:
1. 意外的全局變量
2. 閉包
3. 控制檯日誌
4. 循環引用(在兩個對象彼此引用且彼此保留時,就會產生一個循環)
5. DOM清空或刪除時,時間未清除致使的內存泄漏
6. 被遺忘的定時器或者回調函數
7. setTimeout 的第一個參數使用字符串而非函數的話,會引起內存泄漏。
談談垃圾回收機制方式及內存管理
回收機制方式
一、定義和用法:垃圾回收機制(GC:Garbage Collection),執行環境負責管理代碼執行過程當中使用的內存。
二、原理:垃圾收集器會按期(週期性)找出那些不在繼續使用的變量,而後釋放其內存。可是這個過程不是實時的,由於其開銷比較大,因此垃圾回收器會按照固定的時間間隔週期性的執行。
三、實例以下:
function fn1() {
var obj = {name: 'hanzichi', age: 10};
}
function fn2() {
var obj = {name:'hanzichi', age: 10};
return obj;
}
var a = fn1();var b = fn2();
fn1中定義的obj爲局部變量,而當調用結束後,出了fn1的環境,那麼該塊內存會被js引擎中的垃圾回收器自動釋放;在fn2被調用的過程當中,返回的對象被全局變量b所指向,因此該塊內存並不會被釋放。
垃圾回收策略:標記清除(較爲經常使用)和引用計數。
標記清除:
定義和用法:當變量進入環境時,將變量標記"進入環境",當變量離開環境時,標記爲:"離開環境"。某一個時刻,垃圾回收器會過濾掉環境中的變量,以及被環境變量引用的變量,剩下的就是被視爲準備回收的變量。
到目前爲止,IE、Firefox、Opera、Chrome、Safari的js實現使用的都是標記清除的垃圾回收策略或相似的策略,只不過垃圾收集的時間間隔互不相同。
引用計數:
定義和用法:引用計數是跟蹤記錄每一個值被引用的次數。
基本原理:就是變量的引用次數,被引用一次則加1,當這個引用計數爲0時,被視爲準備回收的對象。
何時觸發垃圾回收?
垃圾回收器週期性運行,若是分配的內存很是多,那麼回收工做也會很艱鉅,肯定垃圾回收時間間隔就變成了一個值得思考的問題。
IE6的垃圾回收是根據內存分配量運行的,當環境中的變量,對象,字符串達到必定數量時觸發垃圾回收。垃圾回收器一直處於工做狀態,嚴重影響瀏覽器性能。
IE7中,垃圾回收器會根據內存分配量與程序佔用內存的比例進行動態調整,開始回收工做。
二、合理的GC方案:(1)、遍歷全部可訪問的對象; (2)、回收已不可訪問的對象。
三、GC缺陷:(1)、中止響應其餘操做;
四、GC優化策略:(1)、分代回收(Generation GC);(2)、增量GC
AMD(Modules/Asynchronous-Definition)、CMD(Common ModuleDefinition)規範區別?
AsynchronousModule Definition,異步模塊定義,全部的模塊將被異步加載,模塊加載不影響後面語句運行。全部依賴某些模塊的語句均放置在回調函數中。
區別:
1. 對於依賴的模塊,AMD 是提早執行,CMD 是延遲執行。不過RequireJS 從 2.0 開始,也改爲能夠延遲執行(根據寫法不一樣,處理方式不一樣)。CMD 推崇 as lazy as possible.
2. CMD 推崇依賴就近,AMD 推崇依賴前置。
對AMD和CMD的理解,它們有什麼區別
AMD和CMD都是爲了解決瀏覽器端模塊化問題而產生的,AMD規範對應的庫函數有 Require.js,CMD規範是在國內發展起來的,對應的庫函數有Sea.js
AMD和CMD最大的區別是對依賴模塊的執行時機處理不一樣
一、AMD推崇依賴前置,在定義模塊的時候就要聲明其依賴的模塊
二、CMD推崇就近依賴,只有在用到某個模塊的時候再去require
什麼冒泡與捕獲?事件委託的原理是什麼?它的使用場景有哪些?
http://www.javashuo.com/article/p-caellqno-h.html
事件冒泡:當一個子元素的事件被觸發的時候(如onclick事件),該事件會從事件源(被點擊的子元素)開始逐級向上傳播,觸發父級元素的點擊事件。
事件委託:便是事件代理:事件委託就是利用事件冒泡,只制定一個時間處理程序,就能夠管理某一類型的全部事件。
將事件處理器綁定到一個父級元素上,避免了頻繁的綁定多個子級元素,依靠事件冒泡機制與事件捕獲機制,子級元素的事件將委託給父級元素。
原理:利用事件冒泡和事件捕獲機制實現的
優勢:只須要將同類元素的事件委託給父級或者更外級的元素,不須要給全部元素都綁定事件,減小內存空間佔用,提高性能; 動態新增的元素無需從新綁定事件
阻止事件冒泡:
w3c的方法是e.stopPropagation(),IE則是使用e.cancelBubble = true
阻止元素默認的行爲(如連接的跳轉、表單的提交):
w3c的方法是e.preventDefault(),IE則是使用e.returnValue = false;
拖拽會用到哪些事件被拖拽元素
dragstart 按下鼠標鍵並開始移動鼠標時
drag 在dragstart事件以後,在元素被拖動期間會持續觸發該事件
dragend 當拖動中止時,會觸發dragend事件
放置目標元素
dragenter 有元素被拖動到放置目標上
dragover 緊隨dragenter發生,在被拖動的元素
還在放置目標範圍內移動時,會持續觸發該事件
dragleave 在元素被拖出放置目標時觸發
drop 元素被放到了放置目標中觸發
註釋:拖拽發生過程:dragstart->drag->dragenter->dragover->dragleave/drop->dragend
Javascript中的定時器有哪些?他們的區別及用法是什麼?
setTimeout 只執行一次
setInterval 會一直重複執行
如何使用ajax?
第一步,建立xmlhttprequest對象,var xmlhttp =new XMLHttpRequest();XMLHttpRequest對象用來和服務器交換數據。
var xhttp;
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest(); //現代主流瀏覽器
} else {
xhttp = new ActiveXObject("Microsoft.XMLHTTP"); // 針對瀏覽器,好比IE5或IE6
}
第二步,使用xmlhttprequest對象的open()和send()方法發送資源請求給服務器。
第三步,使用xmlhttprequest對象的responseText或responseXML屬性得到服務器的響應。
第四步,onreadystatechange函數,當發送請求到服務器,咱們想要服務器響應執行一些功能就須要使用onreadystatechange函數,每次xmlhttprequest對象的readyState發生改變都會觸發onreadystatechange函數
json和xml的區別?
http://www.javashuo.com/article/p-psbsowkt-t.html
JSON的定義
一種輕量級的數據交換格式,具備良好的可讀和便於快速編寫的特性。業內主流技術爲其提供了完整的解決方案(有點相似於正則表達式 ,得到了當今大部分語言的支持),從而能夠在不一樣平臺間進行數據交換。JSON採用兼容性很高的文本格式,同時也具有相似於C語言體系的行爲。
XML的定義
擴展標記語言 (Extensible Markup Language, XML) ,用於標記電子文件使其具備結構性的標記語言,能夠用來標記數據、定義數據類型,是一種容許用戶對本身的標記語言進行定義的源語言。 XML是標準通用標記語言 (SGML) 的子集,很是適合 Web 傳輸。XML 提供統一的方法來描述和交換獨立於應用程序或供應商的結構化數據。
區別:
- 數據體積方面,JSON相對XML來說,數據的體積小,傳遞的速度更快些
- 數據交互方面,JSON與JavaScript的交互更加方便,更容易解析處理,更好地進行數據交互
- 數據描述方面,JSON對數據的描述性比XML較差
- 傳輸速度方面,JSON的速度要遠遠快於XML
json字符串如何轉json對象JSON.stringify(),json對象如何轉json字符串JSON.parse()
請解釋JSONP的工做原理,以及它爲何不是真正的AJAX?
http://www.javashuo.com/article/p-aufasxpw-dw.html
http://www.javashuo.com/article/p-wlovdbkq-bk.html
JSONP (JSON with Padding)是一個簡單高效的跨域方式,HTML中的script標籤能夠加載並執行其餘域的javascript,因而咱們能夠經過script標記來動態加載其餘域的資源。例如我要從域A的頁面pageA加載域B的數據,那麼在域B的頁面pageB中我以JavaScript的形式聲明pageA須要的數據,而後在 pageA中用script標籤把pageB加載進來,那麼pageB中的腳本就會得以執行。JSONP在此基礎上加入了回調函數,pageB加載完以後會執行pageA中定義的函數,所須要的數據會以參數的形式傳遞給該函數。JSONP易於實現,可是也會存在一些安全隱患,若是第三方的腳本隨意地執行,那麼它就能夠篡改頁面內容,截獲敏感數據。可是在受信任的雙方傳遞數據,JSONP是很是合適的選擇。
AJAX是不跨域的,而JSONP是一個是跨域的,還有就是兩者接收參數形式不同!
怎樣添加、移除、移動、複製、建立和查找節點?
1)建立新節點
createDocumentFragment() //建立一個DOM片斷
createElement() //建立一個具體的元素
createTextNode() //建立一個文本節點
2)添加、移除、替換、插入
appendChild() //添加
removeChild() //移除
replaceChild() //替換
insertBefore() //插入
3)查找
getElementsByTagName() //經過標籤名稱
getElementsByName() //經過元素的Name屬性的值
getElementById() //經過元素Id,惟一性
有多個請求第一個完成後才執行第二,第二個完成後才執行第三個,你有幾種方法實現?
方法一:設置ajax的async:false
方法二:用es6的promise
如何防止表單重複提交?有幾種方法?
方法一:定義一個flag=false,改變flag的值
方法二:設置button的禁用屬性
方法三:利用session
WEB應用從服務器主動推送Data到客戶端有那些方式?
html5提供的Websocket
不可見的iframe
WebSocket經過Flash
XHR長時間鏈接
XHR Multipart Streaming
<script>標籤的長時間鏈接(可跨域)
js設計模式
整體來講設計模式分爲三大類:
一、建立型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
二、結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
三、行爲型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模
window的onload事件和domcontentloaded的區別
http://www.javashuo.com/article/p-ckqwejao-x.html
一、當 onload
事件觸發時,頁面上全部的DOM,樣式表,腳本,圖片,flash都已經加載完成了。
二、當 DOMContentLoaded
事件觸發時,僅當DOM加載完成,不包括樣式表,圖片,flash。
jQuery常用$(document).ready();或者$(function(){}) 這都是使用了DOMContentLoaded事件。
JS中的arguments對象
https://cloud.tencent.com/developer/article/1395394
(1)因爲 JavaScript 容許函數有不定數目的參數,因此須要一種機制,能夠在函數體內部讀取全部參數。這就是arguments對象的由來。
(2)arguments對象包含了函數運行時的全部參數,arguments[0]就是第一個參數,arguments[1]就是第二個參數,以此類推。這個對象只有在函數體內部,才能夠使用。
(3)arguments很像數組,但它是一個對象,將其轉換爲數組有兩種方法:
slice方法和逐一填入新數組。
(4)arguments對象有一個名爲callee的屬性,該屬性是一個指針,指向擁有這個arguments對象的函數。但在嚴格模式下,訪問這個屬性會拋出TypeError錯誤
JS中的做用域和做用域鏈
什麼是做用域
做用域是在運行時代碼中的某些特定部分中變量,函數和對象的可訪問性。換句話說,做用域決定了代碼區塊中變量和其餘資源的可見性。
什麼是做用域鏈
若是父級也沒呢?再一層一層向上尋找,直到找到全局做用域仍是沒找到,就宣佈放棄。這種一層一層的關係,就是 做用域鏈 。
實現頁面加載進度條
1.給頁面中重要節點後添加js代碼,改變進度條顯示(以顯示在頁面頭部的進度條爲例)
2.實時監控頁面中加載狀況,
3.document.onreadystatechange監控加載狀態
說明:document.onreadystatechange(頁面加載狀態改變的事件);
document.readyState:
狀態值:uninitialized(還未開始載入),loading(載入中),interactive(已加載,文檔與用戶能夠開始交互),complete(載入完成)。
函數式編程
https://cloud.tencent.com/developer/article/1379522
函數式編程是一種強調以函數使用爲主的軟件開發風格。看到這句我想你仍是一臉懵逼,不知道函數式編程是啥,不要着急,看到最後我相信你會明白的。
還有一點你要記住,函數式編程的目的是使用函數來抽象做用在數據之上的控制流和操做,從而在系統中消除反作用並減小對狀態的改變。
總結
- 使用純函數的代碼毫不會更改或破壞全局狀態,有助於提升代碼的可測試性和可維護性
- 函數式編程採用聲明式的風格,易於推理,提升代碼的可讀性。
- 函數式編程將函數視爲積木,經過一等高階函數來提升代碼的模塊化和可重用性。
- 能夠利用響應式編程組合各個函數來下降事件驅動程序的複雜性(這點後面可能會單獨拿一篇來進行講解)。
怎麼判斷兩個對象是否相等
https://www.jianshu.com/p/90ed8b728975
① 方法一:經過JSON.stringify(obj)
來判斷兩個對象轉後的字符串是否相等
優勢:用法簡單,對於順序相同的兩個對象能夠快速進行比較獲得結果
缺點:這種方法有限制就是當兩個對比的對象中key的順序不是徹底相同時會比較出錯
②方法二:判斷對象相等的步驟:
- 先判斷倆者是否是對象
- 是對象後倆者長度是否一致
- 判斷倆個對象的全部key值是否相等相同
- 判斷倆個對象的相應的key對應的值是否相同
- 來一個遞歸判斷裏面的對象循環1-4步驟
-
function diff(obj1,obj2){
-
var o1 = obj1 instanceof Object;
-
var o2 = obj2 instanceof Object;
-
-
-
-
-
-
-
if (Object.keys(obj1).length !== Object.keys(obj2).length) {
-
-
-
-
-
var t1 = obj1[o] instanceof Object;
-
var t2 = obj2[o] instanceof Object;
-
-
return diff(obj1[o], obj2[o]);
-
}
else if (obj1[o] !== obj2[o]) {
-
-
-
-
-
如何讓事件先冒泡後捕獲
根據w3c標準,應先捕獲再冒泡。若要實現先冒泡後捕獲,給一個元素綁定兩個addEventListener,其中一個第三個參數設置爲false(即冒泡),另外一個第三個參數設置爲true(即捕獲),調整它們的代碼順序,將設置爲false的監聽事件放在設置爲true的監聽事件前面便可。
如何獲取當前日期
/**
*獲取當前時間
*format=1精確到天
*format=2精確到分
*/
function getCurrentDate(format) {
var now = new Date();
var year = now.getFullYear(); //獲得年份
var month = now.getMonth();//獲得月份
var date = now.getDate();//獲得日期
var day = now.getDay();//獲得周幾
var hour = now.getHours();//獲得小時
var minu = now.getMinutes();//獲得分鐘
var sec = now.getSeconds();//獲得秒
month = month + 1;
if (month < 10) month = "0" + month;
if (date < 10) date = "0" + date;
if (hour < 10) hour = "0" + hour;
if (minu < 10) minu = "0" + minu;
if (sec < 10) sec = "0" + sec;
var time = "";
//精確到天
if(format==1){
time = year + "-" + month + "-" + date;
}
//精確到分
else if(format==2){
time = year + "-" + month + "-" + date+ " " + hour + ":" + minu + ":" + sec;
}
return time;
}
alert(getCurrentDate(2));
當即執行函數和使用場景
https://www.jianshu.com/p/b10b6e93ddec
iframe的優缺點有哪些
iframe的優勢:
1.iframe可以原封不動的把嵌入的網頁展示出來。
2.若是有多個網頁引用iframe,那麼你只須要修改iframe的內容,就能夠實現調用的每個頁面內容的更改,方便快捷。
3.網頁若是爲了統一風格,頭部和版本都是同樣的,就能夠寫成一個頁面,用iframe來嵌套,能夠增長代碼的可重用。
4.若是遇到加載緩慢的第三方內容如圖標和廣告,這些問題能夠由iframe來解決。
iframe的缺點:
1.會產生不少頁面,
不容易管理
。
2.iframe框架結構有時會讓人感到迷惑,若是框架個數多的話,可能會出現上下、左右滾動條,會分散訪問者的注意力,
用戶體驗度差
。
3.代碼複雜,沒法被一些搜索引擎索引到,這一點很關鍵,如今的搜索引擎爬蟲還不能很好的處理iframe中的內容,因此使用iframe會
不利於搜索引擎優化
。
4.不少的移動設備(PDA手機)沒法徹底顯示框架,
設備兼容性
差。
5.iframe框架頁面會
增長服務器的http請求
,對於大型網站是不可取的。
分析了這麼多,
如今基本上都是用Ajax來代替iframe,因此iframe已經漸漸的退出了前端開發
。
服務端渲染(SSR)與客戶端渲染(CSR)
服務端渲染(吐)
服務端在返回 html 以前,在特定的區域,符號裏用數據填充,再給客戶端,客戶端只負責解析 HTML 。也被稱爲 fat-server, thin-client 模式
客戶端渲染(填)
html 僅僅做爲靜態文件,客戶端端在請求時,服務端不作任何處理,直接以原文件的形式返回給客戶端客戶端,而後根據 html 上的 JavaScript,生成 DOM 插入 html。也被稱爲 fat-client, thin-server 模式
渲染本質同樣,都是字符串拼接,將數據渲染進一些固定格式的html代碼中造成最終的html展現在用戶頁面上。
拼接字符串必然引發性能的消耗。
服務端渲染性能消耗在服務端,當用戶量比較多時,緩存部分數據以免過多數據重複渲染。
客戶端渲染,如當下火熱的 spa 框架,Angular、React、Vue,在首次渲染時,大可能是將原 html 中的數據標記(如 {{ text }} )替換。客戶端渲染較難的一點是數據更新之後,頁面響應式更新時如何節省資源,直接 DOM 的讀寫,是很消耗性能的。 Vue 2.0 + 有 Vnode,進行 diff 後,渲染到頁面上。
利弊

var的變量提高底層原理是什麼?
http://www.javashuo.com/article/p-bgkujaby-by.html
js自上而下的執行過程分爲兩個詞法分析和執行兩個階段:詞法分析主要包括:分析形參、分析變量聲明、分析函數聲明三個部分.經過詞法分析將咱們寫的js代碼轉成能夠執行的代碼,接下來纔是執行。
變量提高還有一種狀況,就是函數,詞法分析的時候關於函數聲明的處理與變量聲明的處理不太一致,會一步到位的給當前函數活動對象增長對應函數名的屬性,並重寫該方法。也就是不會像變量那樣先賦值undefined了。
建立對象的三種方式
- 經過對象直接量
- 經過new建立對象
- 經過Object.create()
new和Object.create的區別
在 JavaScript 中,構造函數只是一些使用 new 操做符時被調用的函數。
使用 new 來調用函數,或者說發生構造函數調用時,會自動執行下面的操做。
1. 建立(或者說構造)一個全新的對象。
2. 這個新對象會被執行 [[ 原型 ]] ([[Prototype]])鏈接。
3. 這個新對象會綁定到函數調用的 this 。
4. 若是函數沒有返回其餘對象,那麼 new 表達式中的函數調用會自動返回這個新對象。
調用Object.create(..) 會憑空建立一個「新」對象並把新對象內部的 [[Prototype]] 關聯到你指定的對象。
哪一種狀況下__proto__和prototype的指向是同一個?
一個實例對象的__proto__屬性指向自身構造函數的原型鏈,即:
Function.__proto__===Function.prototype;//true
其餘的,好比手動修改__proto__也能夠作到,這種就沒辦法判斷。
varA=function(){}
A.__proto__=A.prototype
A.__proto__===A.prototype;//true
typeof array null undefined NaN分別是什麼
typeof 運算符返回一個用來表示表達式的數據類型的字符串。
可能的字符串有:」number」、」string」、」boolean」、」object」、」function」 和 「undefined」。
1.類型分析:
js中的數據類型有undefined,boolean,number,string,object等5種,前4種爲原始類型,第5種爲引用類型。
var a1;
var a2 = true;
var a3 = 1;
var a4 = 「Hello」;
var a5 = new Object();
var a6 = null;
var a7 = NaN;
var a8 = undefined;
alert(typeof a); //顯示」undefined」
alert(typeof a1); //顯示」undefined」
alert(typeof a2); //顯示」boolean」
alert(typeof a3); //顯示」number」
alert(typeof a4); //顯示」string」
alert(typeof a5); //顯示」object」
alert(typeof a6); //顯示」object」
alert(typeof a7); //顯示」number」
alert(typeof a8); //顯示」undefined」
從上面的代碼中能夠看出未定義的值和定義未賦值的爲undefined,null是一種特殊的object,NaN是一種特殊的number。
2.比較運算
var a1; //a1的值爲undefined
var a2 = null;
var a3 = NaN;
alert(a1 == a2); //顯示」true」
alert(a1 != a2); //顯示」false」
alert(a1 == a3); //顯示」false」
alert(a1 != a3); //顯示」true」
alert(a2 == a3); //顯示」false」
alert(a2 != a3); //顯示」true」
alert(a3 == a3); //顯示」false」
alert(a3 != a3); //顯示」true」
從上面的代碼能夠得出結論:(1)undefined與null是相等;(2)NaN與任何值都不相等,與本身也不相等。Null 數據類型
把undefined和null轉成Number分別是什麼
NAN和0
六種數據類型轉Number規則:
一、Number轉Number,原本多少就是多少;
二、String轉Number:數字字符串轉成對應數字,空字符串轉爲0,其餘均爲NaN;
三、Boolean轉Number:true爲1,false爲0;
四、null爲0,undefined爲NaN;
五、Object(包括對象、函數、數組、正則等)轉Number調用其valueof()方法,若是爲NaN,調用toString()方法,若是仍是NaN,則結果爲NaN。
null和undefined進行"=="比較時不會進行類型轉換可是他們相等,由於undefined派生於null,ECMAScript標準規定兩者進行相等行測試時返回true;
instanceOf和constructor的區別
instanceof 二元運算符
返回一個布爾值,該值指示一個對象是否爲特定類的一個實例。
語法: object instanceof class
instanceof
運算符用來測試一個對象在其原型鏈中是否存在一個構造函數的 prototype
屬性。通俗來將就是判斷一個實例對象是否由某個構造函數構造而來。
nstanceof不只能夠判斷實例對象直接的構造函數,並且還能判斷原型鏈上全部的構造函數。
constructor 屬性,存在於Object.prototype的屬性
返回對象的構造函數,
語法: object.constructor
返回值是函數的引用,不是函數名:
咱們建立的每一個函數都有一個prototype(原型)對象,這個屬性是一個指針,指向一個對象。在默認狀況下,全部原型對象都會自動得到一個constructor(構造函數)屬性,這個屬性是一個指向prototype屬性所在函數的指針。
如何獲取元素的父節點和兄弟節點
https://www.jb51.net/article/143286.htm
JS如何得到用戶來源(navigator.userAgent)
Navigator userAgent 屬性
定義和用法
userAgent 屬性是一個只讀的字符串,聲明瞭瀏覽器用於 HTTP 請求的用戶代理頭的值。
語法
如下代碼能夠判斷目前大部分瀏覽器類別
var browser = {
versions: function() {
var u = navigator.userAgent,
app = navigator.appVersion;
return {
trident: u.indexOf('Trident') > -1, //IE內核
presto: u.indexOf('Presto') > -1, //opera內核
webKit: u.indexOf('AppleWebKit') > -1, //蘋果、谷歌內核
gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐內核
mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否爲移動終端
ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios終端
android: u.indexOf('Android') > -1 || u.indexOf('Adr') > -1, //android終端
iPhone: u.indexOf('iPhone') > -1, //是否爲iPhone或者QQHD瀏覽器
iPad: u.indexOf('iPad') > -1, //是否iPad
webApp: u.indexOf('Safari') == -1, //是否web應該程序,沒有頭部與底部
weixin: u.indexOf('MicroMessenger') > -1, //是否微信 (2015-01-22新增)
qq: u.match(/\sQQ/i) == " qq" //是否QQ
};
}(),
language: (navigator.browserLanguage || navigator.language).toLowerCase()
}
Ajax返回204算是成功嗎
204請求成功了,可是沒有結果返回來。
205 Reset Content, 表示執行成功, 重置頁面(Form表單).
總的來講, 204適合屢次對一個Item進行更新, 而205則適合屢次提交一個系列的Item.
但, 請注意, 目前尚未一個瀏覽器支持205, 大部分的瀏覽器, 都會把205當作204或者200一樣對待.
棧和隊列有什麼區別,具體的應用場景
1.是什麼?
棧和隊列實際上是一個工具,他們傳統的工具方法 工具類不一樣,他們是「思想」工具,你們都知道,棧是後進先出,隊列是先進先出。可是實際怎麼用殊不知道。
2.怎麼用?
棧和隊列是很好的工具,他們的應用咱們平時開發可能用到得少,可是在實際中,他們的應用很是多。
棧:棧後進先出的特色,能夠很好的控制訪問控制,棧的數據訪問是有很嚴格的,只能訪問最後加入的數據,這對數據訪問控制嚴格的應用頗有好處。現實中,字符串倒序輸出,使用棧的原理就能夠很好的實現。
隊列:隊列能夠模擬不少現實的生產環境,例如排隊,隊列是先進先出,不容許有任何元素插隊,這對於解決現實生產問題有很大幫助。
優勢:棧和隊列的操做的時間複雜度都是O(1),效率很是高。
Ajax如何實現的
https://www.jianshu.com/p/8eed5f8291ed
preventDefault()、stopPropagation()、return false之間的區別
preventDefault():阻止事件默認行爲;
stopPropagation():阻止事件冒泡;
return false:當你每次調用」return false「的時候,它實際上作了3件事情:
•event.preventDefault();
•event.stopPropagation();
•中止回調函數執行並當即返回。
頁面共享數據的方法有哪些
1.表單隱藏域;
2.url傳遞;
3.storage;
4.vue-route;
5.vuex
js如何實現一個棧
棧的JS實現
棧,是一種特殊的線性表,其插入及刪除的操做都在線性表的同一端進行。這一端稱爲棧頂,另外一端稱爲棧底。就相似於餐廳裏的一摞盤子,後放的盤子在上方,也會先被人拿走。棧具備「後進先出」的邏輯特性。棧在計算機科學中有着普遍的應用,遞歸函數的實現就利用了棧這種數據結構,在遞歸時,計算機會維護一個遞歸工做棧,當一個遞歸函數被調用時,被調函數的局部變量、形參的值以及一個返回地址就會儲存在遞歸工做棧中。運行時按照後進先出的順序,進行函數執行,完成遞歸操做。編譯原理中也屢次使用棧這種數據結構~

棧是一種特殊的線性表,故其在存儲結構上也有鏈式存儲和順序存儲兩種。代碼以下:
- function LinkedStack(){
-
- var Node = function(element){
- this.element = element;
- this.next = null;
- }
-
- var length = 0,
- top;
-
- this.push = function(element){
- var node = new Node(element),
- current;
-
- if(!top){
- top = node;
- length++;
- return true;
- }else{
- node.next = top;
- top = node;
- length++;
- return true;
- }
- }
-
- this.pop = function(){
- var current = top;
- if(top){
- top = current.next;
- current.next = null;
- length--;
- return current;
- }else{
- return 'null stack';
- }
- }
-
- this.top = function(){
- return top;
- }
-
- this.size = function(){
- return length;
- }
-
- this.toString = function(){
- var string = '',
- current = top;
-
- while(current){
- string += current.element;
- current = current.next;
- }
-
- return string;
- }
-
- this.clear = function(){
- top = null;
- length = 0;
-
- return true;
- }
- }
-
- function ArrayStack(){
- var arr = [];
-
- this.push = function(element){
- arr.push(element);
- }
-
- this.pop = function(){
- return arr.pop();
- }
-
- this.top = function(){
- return arr[arr.length-1];
- }
-
- this.size = function(){
- return arr.length;
- }
-
- this.clear = function(){
- arr = [];
- return true;
- }
-
- this.toString = function(){
- return arr.toString();
- }
- }
哈希表是怎麼樣的結構
https://www.cnblogs.com/yangecnu/p/Introduce-Hashtable.html
哈希表就是一種以 鍵-值(key-indexed) 存儲數據的結構,咱們只要輸入待查找的值即key,便可查找到其對應的值。
哈希的思路很簡單,若是全部的鍵都是整數,那麼就能夠使用一個簡單的無序數組來實現:將鍵做爲索引,值即爲其對應的值,這樣就能夠快速訪問任意鍵的值。這是對於簡單的鍵的狀況,咱們將其擴展到能夠處理更加複雜的類型的鍵。
使用哈希查找有兩個步驟:
- 使用哈希函數將被查找的鍵轉換爲數組的索引。在理想的狀況下,不一樣的鍵會被轉換爲不一樣的索引值,可是在有些狀況下咱們須要處理多個鍵被哈希到同一個索引值的狀況。因此哈希查找的第二個步驟就是處理衝突
- 處理哈希碰撞衝突。有不少處理哈希碰撞衝突的方法,本文後面會介紹拉鍊法和線性探測法。
哈希表是一個在時間和空間上作出權衡的經典例子。若是沒有內存限制,那麼能夠直接將鍵做爲數組的索引。那麼全部的查找時間複雜度爲O(1);若是沒有時間限制,那麼咱們能夠使用無序數組並進行順序查找,這樣只須要不多的內存。哈希表使用了適度的時間和空間來在這兩個極端之間找到了平衡。只須要調整哈希函數算法便可在時間和空間上作出取捨。
說說操做系統的內存管理
http://www.javashuo.com/article/p-giwgprsx-mr.html
怎麼樣實現一個服務器
https://cloud.tencent.com/developer/article/1448267
https://cloud.tencent.com/developer/news/6596
假如訪問A.com存進了一個cookie,在另一個頁面用ajax向A的域名發請求會攜帶cookie嗎
ajax跨域傳遞cookie
http://www.javashuo.com/article/p-nxptvmyo-be.html
一級域名相同,只是二級域名不一樣的狀況下,瀏覽器容許經過設置document.domain共享Cookie。也就是說,Cookie只能跨二級域名來訪問,不能跨一級域名來訪問。
經過修改請求頭是能夠傳遞cookie等信息的。可是w3c的標準寫的很清楚,cookie,connection和content-length等是不安全的字段,容易致使多種的request smuggling攻擊,不容許編程設置。這些字段瀏覽器會自動幫你設置,若是設置就會報出錯誤:「Refused to set unsafe header "Content-Length"。
既然ajax跨域中直接設置請求頭是不容許的,那麼咱們就必須在ajax請求發出以前就應該設置cookie,而後ajax請求時會自動去填充請求頭header內容(其中cookie內容會自動從硬盤中讀取)。同時服務器端也要作些返回頭的修改:response.setHeader("Access-Control-Allow-Credentials","true");
localStorage存儲數據格式是什麼?怎麼樣把一個數組存進localSorage?
localStorage存儲數據的格式都是以字符串的形式來存儲的,
存儲數組對象的方式就是將數組對象轉爲字符串,在讀取的時候再將字符串轉成數組對象
表單提交和ajax的區別
有以下幾種區別:
1. Ajax在提交、請求、接收時,都是異步進行的,網頁不須要刷新;Form提交則是新建一個頁面,哪怕是提交給本身自己的頁面,也是須要刷新的;
2. A在提交時,是在後臺新建一個請求;F倒是放棄本頁面,然後再請求;
3. A必需要使用JS來實現,不啓用JS的瀏覽器,沒法完成該操做;F倒是瀏覽器的本能,不管是否開啓JS,均可以提交表單; 4. A在提交、請求、接收時,整個過程都須要使用程序來對其數據進行處理;F提交時,倒是根據你的表單結構自動完成,不須要代碼干預。
JS中的事件綁定、事件監聽、事件委託是什麼?
http://www.javashuo.com/article/p-dsrfhtwg-k.html
寫一個API實現insertAfter
DOM裏有insertBefore函數,但沒有insertAfter函數,因此本身編寫一個該函數:
Element.prototype.insertAfter=
function (newElement, targetElement){
var parent = targetElement.parentNode;//獲取父級元素節點
if(parent.lastChild == targetElement){//若是目標元素是父級元素的最後一個子元素
parent.appendChild(newElement);
}else{//若是不是最後一個子元素,則調用insertBefore函數
parent.insertBefore(newElement,targetElement.nextSibling);
}
}
JS的如何實現倒計時,爲何不許,校訂方式
http://www.javashuo.com/article/p-ouktlzts-z.html
前端倒計時許考慮兩個問題:
1.因爲js是單線程的,也就是阻塞的,定時可定會不許。不管setTimeout()仍是setInterval(),都有問題;
二、打開瀏覽器,而後切換到其餘app,再次回到瀏覽器,這期間js可能中止執行的問題。
本質上來講,只須要兩個時間點就能夠了:當前時間、秒殺開始時間。有了這兩個數據,咱們就能夠倒計時了。兩個時間的差值就是咱們要倒計時的時間差,每隔1秒減小1/每隔1毫秒減小1。可是,當前的時間不要用new Date(),這是獲取手機的時間,若是用戶修改手機的時間,這個會跟隨變化的。基於此,當前的時間必須是服務端傳過來的。用戶每次打開網頁,都會傳服務器的當前時間。秒殺開始的時間通常是後臺配置好的,只要配置了,他就定了。是個不變的量。
解決方法1:
以服務器的當前時間爲倒計時的當前時間,上面提到須要考慮的那兩個問題都沒有解決,若是咱們實時同步服務器的當前時間,那麼這兩個問題就都解決了。
如什麼時候時同步呢?最早想到的是,時時調用一個後端的接口,這個接口返回服務器的當前時間。但實際上,咱們只須要跟服務器ajax交互就能夠了,請求一個服務器不存在的資源,咱們從返回中拿返回頭,再從這個頭中取服務器的當前時間。
這種方法就是不斷的同步服務器的事件。
以上代碼的欠缺是每次請求服務器,性能不佳。但好處也顯而易見,3個用戶同時訪問頁面,他們的倒計時結果基本上同樣的,秒殺變得比較公平。當服務器出現問題,請求不到服務器的當前時間,這個代碼會有問題,但這不是咱們考慮的問題。
解決方法2:
還有種解決的辦法,就是計算每次倒計時的偏差,你能知道第n次你倒計時的應該發生的時間,再跟當前的時間對比,這個偏差就在下次倒計時的時候考慮進去。這樣能夠保證偏差不累計。可是對於退出瀏覽器的行爲,這種實際上是有問題的。
這種方法是不斷校準倒計時的週期,而週期不可能爲負數,治標不治本。
實現一個ajax,兼容
function ajax() {
var oBtn = document.getElementById('btn');
oBtn.onclick = function() {
/*
1.建立一個ajax對象
ie6如下new ActiveXObject('Microsoft.XMLHTTP')
*/
var xhr = null;
//第一種處理兼容方式
/*if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest(); //Firefox(或其餘非IE)
} else {
xhr = new ActiveXObject('Microsoft.XMLHTTP'); //IE瀏覽器
}*/
//第二種處理兼容方式
try {
xhr = new XMLHttpRequest();
} catch (e) {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
/*
open方法
參數
1.打開方式
2.地址
3.是否異步
異步:非阻塞 前面的代碼不會影響後面代碼的執行
同步:阻塞 前面的代碼會影響後面代碼的執行
*/
xhr.open('get','links/1.txt',true);
//提交 發送請求
xhr.send();
//等待服務器返回內容
xhr.onreadystatechange = function() {
if ( xhr.readyState == 4 ) {
alert( xhr.responseText );
}
}
}
}
假設一個object A裏面的值n爲1,怎麼樣知道n改變了,有事件綁定嗎
設置一個js變量
var obj = {};
監聽方法
Object.defineProperty(obj,'data', { get: function () { return data; }, set: function (newValue) { data = newValue; console.log(newValue);//成功觸發方法打印出設置的值 } });