爲了方便如今和之後前端學習和麪試,在此收集和整理了Js相關的筆試面試題,供本身查閱的同時,但願也會對你們有所幫助。javascript
前端HTML+CSS筆試題面試題
前端JS筆試題面試題
前端Vue筆試題面試題
前端小程序筆試題面試題html
Undefined、Null、Boolean、Number、String
新增:Symbol
前端
Object
是 JavaScript
中全部對象的父對象
數據封裝類對象:Object、Array、Boolean、Number
和 String
其餘對象:Function、Arguments、Math、Date、RegExp、Error
java
typeof undefinded //undefined
typeof null // object
typeof'abc' // string
typeof 123 // number
typeof [] // object
typeof {} // object
typeof true //boolean
typeof b // b 沒有聲明,可是還會顯示 undefined
複製代碼
===
什麼時候使用==
?(考點:強制類型轉換)==
比較兩個值相等返回ture
===
比較二者的值和類型都相等才返回true
嚴格相等 0,NAN,null,undefinded,'',false
在if
語句中會強制轉化爲 false
node
if (obj.a == null) {
// 這裏至關於 obj.a === null || obj.a ===undefinded, 簡寫形式
// 這裏jquery 源碼中推薦的寫法
}
複製代碼
null,undefined
的區別?一、null
: Null
類型,表明「空值」,表明一個空對象指針,使用typeof
運算獲得 「object」
,因此你能夠認爲它是一個特殊的對象值。
二、undefined
: Undefined
類型,當一個聲明瞭一個變量未初始化時,獲得的就是undefined
。jquery
ps:一句話簡單來講null
和undefine
值比較是相等,但類型不一樣。nginx
一、對象字面量的方式面試
var = {}
複製代碼
二、經過構造函數方式建立。ajax
var obj = new Object();
複製代碼
三、經過Object.create()
方式建立。算法
var obj = Object.create(Object.prototype);
複製代碼
能夠先將字符串轉成一個數組,而後用數組的reverse()+join()
方法。
let str="hello word";
let b=[...str].reverse().join("");//drow olleh
複製代碼
new
一個對象的過程一、建立一個新對象
二、this
指向這個對象
三、執行代碼,即對this
賦值
四、隱式返回this
// 值類型
var a = 10
var b = a
a = 11
console.log(b) // 10
// 引用類型
var obj1 = {x : 100}
var obj2 = obj1
obj1.x = 200
console.log(obj2) // 200
複製代碼
一、instanceof
方法 instanceof
運算符是用來測試一個對象是否在其原型鏈原型構造函數的屬性
var arr = [];
arr instanceof Array; // true
複製代碼
二、constructor
方法 constructor
屬性返回對建立此對象的數組函數的引用,就是返回對象相對應的構造函數
var arr = [];
arr.constructor == Array; //true
複製代碼
三、最簡單的方法,這種寫法兼容性最好使用Object.prototype.toString.call()
function isObjArr(value){
if (Object.prototype.toString.call(value) === "[object Array]") {
console.log('value是數組');
}else if(Object.prototype.toString.call(value)==='[object Object]'){//這個方法兼容性好一點
console.log('value是對象');
}else{
console.log('value不是數組也不是對象')
}
}
複製代碼
四、ES5
新增方法isArray()
var a = new Array(123);
var b = new Date();
console.log(Array.isArray(a)); //true
console.log(Array.isArray(b)); //false
複製代碼
ps:千萬不能使用typeof
來判斷對象和數組,由於這兩種類型都會返回"object"
。
一、Set
結構去重(ES6
用法)。 ES6
提供了新的數據結構Set
。它相似於數組,可是成員的值都是惟一的,沒有重複的值。
[...new Set(array)];
複製代碼
二、遍歷,將值添加到新數組,用indexOf()
判斷值是否存在,已存在就不添加,達到去重效果。
let a = ['1','2','3',1,NaN,NaN,undefined,undefined,null,null, 'a','b','b'];
let unique= arr =>{
let newA=[];
arr.forEach(key => {
if( newA.indexOf(key)<0 ){ //遍歷newA是否存在key,若是存在key會大於0就跳過push的那一步
newA.push(key);
}
});
return newA;
}
console.log(unique(a)) ;//["1", "2", "3", 1, NaN, NaN, undefined, null, "a", "b"]
// 這個方法不能分辨NaN,會出現兩個NaN。是有問題的,下面那個方法好一點。
複製代碼
三、利用for
嵌套for
,而後splice
去重(ES5
中最經常使用)。
function unique(arr){
for(var i=0; i<arr.length; i++){
for(var j=i+1; j<arr.length; j++){
if(arr[i]==arr[j]){ //第一個等同於第二個,splice方法刪除第二個
arr.splice(j,1);
j--;
}
}
}
return arr;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}] //NaN和{}沒有去重,兩個null直接消失了
複製代碼
四、forEach
遍歷,而後利用Object.keys(對象)
返回這個對象可枚舉屬性組成的數組,這個數組就是去重後的數組。
let a = ['1', '2', '3', 1,NaN,NaN,undefined,undefined,null,null, 'a', 'b', 'b'];
const unique = arr => {
var obj = {}
arr.forEach(value => {
obj[value] = 0;//這步新添加一個屬性,並賦值,若是不賦值的話,屬性會添加不上去
})
return Object.keys(obj);//`Object.keys(對象)`返回這個對象可枚舉屬性組成的數組,這個數組就是去重後的數組
}
console.log(unique(a));//["1", "2", "3", "NaN", "undefined", "null", "a", "b"]
複製代碼
var、let、const
之間的區別var
聲明變量能夠重複聲明,而let
不能夠重複聲明 var
是不受限於塊級的,而let
是受限於塊級 var
會與window
相映射(會掛一個屬性),而let
不與window
相映射 var
能夠在聲明的上面訪問變量,而let
有暫存死區,在聲明的上面訪問變量會報錯 const
聲明以後必須賦值,不然會報錯 const
定義不可變的量,改變了就會報錯 const
和let
同樣不會與window
相映射、支持塊級做用域、在聲明的上面訪問變量會報錯
This
幾種不一樣的使用場景一、做爲構造函數執行
二、做爲對象屬性執行
三、做爲普通函數執行
四、call apply bind
This
對象的理解一、this
老是指向函數的直接調用者(而非間接調用者)
二、若是有new
關鍵字,this
指向new
出來的那個對象
三、在事件中,this
指向觸發這個事件的對象,特殊的是,IE
中的attachEvent
中的this
老是指向全局對象Window
ES5
做用域分爲 全局做用域 和 函數做用域。 ES6
新增塊級做用域,塊做用域由 { }
包括,if
語句和 for
語句裏面的{ }
也屬於塊做用域。
// 塊級做用域
if (true) {
var name = 'zhangsan'
}
console.log(name)
// 函數和全局做用域
var a = 100
function fn () {
var a = 200
console.log('fn', a)
}
複製代碼
JS
建立10個<a>
標籤,點擊的時候彈出來對應的序號?(考點:做用域)var i
for (i = 0; i < 10; i++) {
(function (i) {
var a = document.createElement('a')
a.innerHTML = i + '<br>'
a.addEventListener('click', function (e) {
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
})(i)
}
複製代碼
一、做用域鏈的做用是保證執行環境裏有權訪問的變量和函數是有序的,做用域鏈的變量只能向上訪問,變量訪問到window
對象即被終止,做用域鏈向下訪問變量是不被容許的
二、簡單的說,做用域就是變量與函數的可訪問範圍,即做用域控制着變量與函數的可見性和生命週期
三、通俗來講,通常狀況下,變量取值到 建立 這個變量 的函數的做用域中取值。 可是若是在當前做用域中沒有查到值,就會向上級做用域去查,直到查到全局做用域,這麼一個查找過程造成的鏈條就叫作做用域鏈
var a = 100
function fn () {
var b = 200
// 當前做用域沒有定於的變量,即‘自由變量’
console.log(a)
console.log(b)
}
fn()
console.log(a) 去父級做用域找a自由變量 做用域鏈
複製代碼
閉包就是可以讀取其餘函數內部變量的函數
閉包是指有權訪問另外一個函數做用域中變量的函數,建立閉包的最多見的方式就是在一個函數內建立另外一個函數,經過另外一個函數訪問這個函數的局部變量,利用閉包能夠突破做用鏈域
function F1 () {
var a = 100
// 返回一個函數,函數做爲返回值
return function () {
console.log(a)
}
}
// f1 獲得一個函數
var f1 = F1()
var a = 200
f1() // 100 定義的時候父級做用域
複製代碼
函數內再嵌套函數
內部函數能夠引用外層的參數和變量
參數和變量不會被垃圾回收機制回收
使用閉包主要是爲了設計私有的方法和變量。閉包的優勢是能夠避免全局變量的污染,缺點是閉包會常駐內存,會增大內存使用量,使用不當很容易形成內存泄露。在js中,函數即閉包,只有函數纔會產生做用域的概念
閉包的最大用處有兩個,一個是能夠讀取函數內部的變量,另外一個就是讓這些變量始終保持在內存中
閉包的另外一個用處,是封裝對象的私有屬性和私有方法
好處:可以實現封裝和緩存等;
壞處:就是消耗內存、不正當使用會形成內存溢出的問題
因爲閉包會使得函數中的變量都被保存在內存中,內存消耗很大,因此不能濫用閉包,不然會形成網頁的性能問題,在IE中可能致使內存泄露 解決方法是,在退出函數以前,將不使用的局部變量所有刪除
閉包的兩個場景:函數做爲返回值 和 函數做爲參數傳遞
function F1 () {
var a = 100
// 返回一個函數,函數做爲返回值
return function () {
console.log(a)
}
}
// f1 獲得一個函數
var f1 = F1()
var a = 200
f1() // 100 定義的時候父級做用域
function F2 (fn) {
var a = 200
fn()
}
F2(f1)
複製代碼
// 閉包實際應用中主要用於封裝變量 收斂權限
function isFirstLoad() {
var _list = []
return function (id) {
if (_list.indexOf(id) >= 0) {
return false
} else {
_list.push(id)
return true
}
}
}
// 使用
var firstLoad = new isFirstLoad()
firstLoad(10) //true
firstLoad(10) //false
firstLoad(30) //true
複製代碼
每一個對象都會在其內部初始化一個屬性,就是prototype
(原型), 當咱們訪問一個對象的屬性時,若是這個對象內部不存在這個屬性,那麼他就會去prototype
裏找這個屬性,這個prototype
又會有本身的prototype
,因而就這樣一直找下去,也就是咱們平時所說的原型鏈的概念
原型和原型鏈關係
關係:instance.constructor.prototype = instance.__proto__
原型和原型鏈特色
JavaScript
對象是經過引用來傳遞的,咱們建立的每一個新對象實體中並無一份屬於本身的原型副本。當咱們修改原型時,與之相關的對象也會繼承這一改變 當咱們須要一個屬性的時,Javascript
引擎會先看當前對象中是否有這個屬性, 若是沒有的 就會查找他的Prototype對象是否有這個屬性,如此遞推下去,一直檢索到 Object
內建對象
PS: 1.全部的引用類型(數組,對象,函數)都具備對象的特性,便可自由擴展屬性(除了‘null
’)除外
2.全部的引用類型(數組,對象,函數)都有一個_proto_
(隱式原型)屬性,屬性值是一個普通對象
3.全部的函數,都有一個prototype
(顯示原型)的屬性,也是一個普通對象
4.全部的引用類型(數組,對象,函數)_proto_
屬性值指向他的構造的‘prototype
’ 屬性值
_proto_
(即它的構造函數的prototype
) 中尋找// 構造函數
function Foo(name, age){
this.name = name
}
Foo.prototype.alertName = function () {
alert(this.name)
}
//建立實例
var f = new Foo('zhangsan')
f.printName = function () {
console.log(this.name)
}
//測試
f.printName()
f.alertName()
複製代碼
var item
for (item in f) {
// 高級瀏覽器已經在 for in 中屏蔽了來自原型的屬性
// 可是這裏建議你們仍是加上這個判斷,保證程序的健壯性
if (f.hasOwnProperty(item)) {
console.log(item)
}
}
複製代碼
f.toString() //到f._proto_._proto_ 中去找
複製代碼
同步交互
:指發送一個請求,須要等待返回,而後纔可以發送下一個請求,有個等待過程。 異步交互
:指發送一個請求,不須要等待返回,隨時能夠再發送下一個請求,即不須要等待。 相同的地方
:都屬於交互方式,都是發送請求。 不一樣的地方
:一個須要等待,一個不須要等待。
簡單而言,同步就是必須一件一件的作事,等前一件事作完後才能作下一件事。而異步這是把事情指派給別人後,接着繼續作下一件事,沒必要等別人返回的結果。
舉例:
一、廣播,就是一個異步例子。發起者不關心接收者的狀態。不須要等待接收者的返回信息; 在部分狀況下,咱們的項目開發中都會優先選擇不須要等待的異步交互方式。
二、電話,就是一個同步例子。發起者須要等待接收者,接通電話後,通訊纔開始。須要等待接收者的返回信息 好比銀行的轉帳系統,對數據庫的保存操做等等,都會使用同步交互操做。
ps: alert
是同步,setTimeout
和setInterval
是異步,同步會阻塞代碼執行,而異步不會
一、回調函數
優勢:簡單、容易理解
缺點:不利於維護,代碼耦合高
二、事件監聽(採用時間驅動模式,取決於某個事件是否發生):
優勢:容易理解,能夠綁定多個事件,每一個事件能夠指定多個回調函數
缺點:事件驅動型,流程不夠清晰
三、發佈/訂閱(觀察者模式)
相似於事件監聽,可是能夠經過‘消息中心’,瞭解如今有多少發佈者,多少訂閱者
四、Promise對象
優勢:能夠利用then
方法,進行鏈式寫法;能夠書寫錯誤時的回調函數;
缺點:編寫和理解,相對比較難
五、Generator函數
優勢:函數體內外的數據交換、錯誤處理機制
缺點:流程管理不方便
六、async函數
優勢:內置執行器、更好的語義、更廣的適用性、返回的是Promise
、結構清晰。
缺點:錯誤處理機制
簡單來講:由於js
是單線程的,瀏覽器遇到setTimeout
或者setInterval
會先執行完當前的代碼塊,在此以前會把定時器推入瀏覽器的待執行事件隊列裏面,等到瀏覽器執行完當前代碼以後會看一下事件隊列裏面有沒有任務,有的話才執行定時器的代碼。 因此即便把定時器的時間設置爲0
仍是會先執行當前的一些代碼。
setTimeout
的筆試題console.log(1)
setTimeout(function () {
console.log(2)
},0)
console.log(3)
setTimeout(function () {
console.log(4)
},1000)
console.log(5)
//結果爲 1 3 5 2 4
複製代碼
一、定時任務:setTimeout,setInverval
二、網絡請求:ajax
請求,動態<img>
加載
三、事件綁定
API
一、forEach
方法,是最基本的方法,就是遍歷與循環,默認有3個傳參:分別是遍歷的數組內容item
、數組索引index
、和當前遍歷數組Array
二、map
方法,基本用法與forEach
一致,可是不一樣的,它會返回一個新的數組,因此在callback
須要有return
值,若是沒有,會返回undefined
一般咱們會用循環的方式來遍歷數組。可是循環是 致使js 性能問題的緣由之一。通常咱們會採用下幾種方式來進行數組的遍歷 for in循環
for循環
forEach
一、這裏的 forEach
回調中兩個參數分別爲 value,index
二、forEach
沒法遍歷對象
三、IE
不支持該方法;Firefox
和 chrome
支持
四、forEach
沒法使用 break,continue
跳出循環,且使用 return
是跳過本次循環
五、能夠添加第二個參數,爲一個數組,回調中的this會指向這個數組,若沒有添加,則是指向window
;
在方式一中,for-in
須要分析出array
的每一個屬性,這個操做性能開銷很大。用在 key
已知的數組上是很是不划算的。因此儘可能不要用for-in
,除非你不清楚要處理哪些屬性,例如JSON
對象這樣的狀況
在方式2中,循環每進行一次,就要檢查一下數組長度。讀取屬性(數組長度)要比讀局部變量慢,尤爲是當array
裏存放的都是 DOM
元素,由於每次讀取都會掃描一遍頁面上的選擇器相關元素,速度會大大下降
forEach
函數function forEach(obj, fn) {
var key
// 判斷類型
if (obj instanceof Array) {
obj.forEach(function (item, index) {
fn(index, item)
})
} else {
for (key in obj) {
fn ( key, obj[key])
}
}
}
複製代碼
API
map: 遍歷數組,返回回調返回值組成的新數組
forEach: 沒法break,能夠用try/catch中throw new Error來中止
filter: 過濾
some: 有一項返回true,則總體爲true
every: 有一項返回false,則總體爲false
join: 經過指定鏈接符生成字符串
push / pop: 末尾推入和彈出,改變原數組, 返回推入/彈出項【有誤】
unshift / shift: 頭部推入和彈出,改變原數組,返回操做項【有誤】
sort(fn) / reverse: 排序與反轉,改變原數組
concat: 鏈接數組,不影響原數組, 淺拷貝
slice(start, end): 返回截斷後的新數組,不改變原數組
splice(start, number, value...): 返回刪除元素組成的數組,value 爲插入項,改變原數組
indexOf / lastIndexOf(value, fromIndex): 查找數組項,返回對應的下標
reduce / reduceRight(fn(prev, cur), defaultPrev): 兩兩執行,prev 爲上次化簡函數的return值,cur 爲當前值(從第二項開始)
複製代碼
API
var obj = {
x: 100,
y: 200,
z: 300
}
var key
for (key in obj) {
// 注意這裏的 hasOwnProperty,再講原型鏈的時候講過
if (obj.hasOwnProperty(key)) {
console.log(key, obj[key])
}
}
複製代碼
2020-06-10
格式的日期Date.now() // 獲取當前時間毫秒數
var dt = new Date()
dt.getTime() //獲取毫秒數
dt.getFullYear() // 年
dt.getMonth() // 月 (0-11)
dt.getDate() // 日 (0-31)
dt.getHours() // 小時 (0-23)
dt.getMinutes() //分鐘 (0-59)
dt.getSeconds() //秒 (0-59)
複製代碼
ps: ES6
新增padStart(),padEnd()
方法可用來返回06
格式日期
var random = Math.random()
var random = random + '0000000000'
console.log(random)
var random = random.slice(0, 10)
console.log(random)
複製代碼
DOM
和BOM
操做DOM
是哪一種基本的數據結構DOM
是一種樹形結構的數據結構
DOM
操做的經常使用API
有哪些一、獲取DOM
節點,以及節點的property
和Attribute
二、獲取父節點,獲取子節點
三、新增節點,刪除節點
DOM
節點的Attribute
和property
有何區別property
只是一個JS
對象的屬性修改和獲取 Attribute
是對html
標籤屬性的修改和獲取
DOM
的節點操做建立新節點
createDocumentFragment() //建立一個DOM片斷
createElement() //建立一個具體的元素
createTextNode() //建立一個文本節點
複製代碼
添加、移除、替換、插入
appendChild() //添加
removeChild() //移除
replaceChild() //替換
insertBefore() //插入
複製代碼
查找
getElementsByTagName() //經過標籤名稱
getElementsByName() //經過元素的Name屬性的值
getElementById() //經過元素Id,惟一性
複製代碼
如何檢測瀏覽器的類型
能夠經過檢測navigator.userAgent
在經過不通瀏覽器的不通來檢測
var ua = navigator.userAgent
var isChrome = ua.indexOf('Chrome')
console.log(isChrome)
複製代碼
拆解url
的各部分
使用location
裏面的location.href location.protocol location.pathname location.search location.hash
來獲取各類參數
console.log(location.href)
console.log(location.host) //域名
console.log(location.protocol)
console.log(location.pathname) //路徑
console.log(location.search) // 參數
console.log(location.hash)
// history
history.back()
history.forward()
複製代碼
事件代理(Event Delegation
),又稱之爲事件委託。是 JavaScript
中經常使用綁定事件的經常使用技巧。顧名思義,「事件代理」便是把本來須要綁定的事件委託給父元素,讓父元素擔當事件監聽的職務。事件代理的原理是DOM
元素的事件冒泡。
使用事件代理的好處是:
一、能夠提升性能
二、能夠大量節省內存佔用,減小事件註冊,好比在table
上代理全部td
的click
事件就很是棒
三、能夠實現當新增子對象時無需再次對其綁定
W3C
中定義事件的發生經歷三個階段:捕獲階段(capturing)、目標階段(targetin)、冒泡階段(bubbling)
冒泡型事件:
當你使用事件冒泡時,子級元素先觸發,父級元素後觸發 捕獲型事件:
當你使用事件捕獲時,父級元素先觸發,子級元素後觸發 DOM事件流:
<時支持兩種事件模型:捕獲型事件和冒泡型事件 阻止冒泡:
在W3c
中,使用stopPropagation()
方法;在IE
下設置cancelBubble = true
阻止捕獲:
阻止事件的默認行爲,例如click - <a>後
的跳轉。在W3c
中,使用preventDefault()
方法,在IE
下設置window.event.returnValue = false
function bindEvent(elem,type,selector,fn){
if(fn==null){
fn = selector;
selector = null
}
elem.addEventListener(type,function(e){
var target;
if(selector){
target = e.target;
if(target.matches(selector)){
fn.call(target,e)
}
}else{
fn(e)
}
})
}
複製代碼
當給某元素綁定一個事件的時候,首先會觸發本身綁定的,而後會逐層向上級查找事件,這就是事件冒泡
var p1 = document.getElementById('p1')
var body = document.body
function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
bindEvent(p1, 'click', function (e) {
e.stopPropagation()
var target = e.target
alert("激活")
})
bindEvent(body, 'click', function (e) {
var target = e.target
alert("取消")
})
複製代碼
可使用代理,經過對父級元素綁定一個事件,經過判斷事件的target
屬性來進行判斷,添加行爲
var div1 = document.getElementById('div1')
var div2 = document.getElementById('div2')
function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
bindEvent(div1, 'click', function (e) {
var target = e.target
alert(target.innerHTML)
})
bindEvent(div2, 'click', function (e) {
var target = e.target
alert(target.innerHTML)
})
複製代碼
Ajax
原理Ajax
的原理簡單來講是在用戶和服務器之間加了—箇中間層(AJAX
引擎),經過XmlHttpRequest
對象來向服務器發異步請求,從服務器得到數據,而後用javascript
來操做DOM
而更新頁面。使用戶操做與服務器響應異步化。這其中最關鍵的一步就是從服務器得到請求數據 Ajax
的過程只涉及JavaScript、XMLHttpRequest和DOM
。XMLHttpRequest
是ajax的核心機制
ajax
,不依賴第三方庫// 1. 建立鏈接
var xhr = null;
xhr = new XMLHttpRequest()
// 2. 鏈接服務器
xhr.open('get', url, true)
// 3. 發送請求
xhr.send(null);
// 4. 接受請求
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
success(xhr.responseText);
} else { // fail
fail && fail(xhr.status);
}
}
}
複製代碼
ajax
的優勢和缺點
ajax的優勢
一、無刷新更新數據(在不刷新整個頁面的狀況下維持與服務器通訊)
二、異步與服務器通訊(使用異步的方式與服務器通訊,不打斷用戶的操做)
三、前端和後端負載均衡(將一些後端的工做交給前端,減小服務器與寬度的負擔)
四、界面和應用相分離(ajax
將界面和應用分離也就是數據與呈現相分離)
ajax的缺點
一、ajax不支持瀏覽器back按鈕
二、安全問題 Aajax
暴露了與服務器交互的細節
三、對搜索引擎的支持比較弱
四、破壞了Back
與History
後退按鈕的正常行爲等瀏覽器機制。
跨域問題是這是瀏覽器爲了安全實施的同源策略致使的,同源策略限制了來自不一樣源的document、腳本
,同源的意思就是兩個URL
的域名、協議、端口要徹底相同。 script
標籤jsonp
跨域、nginx
反向代理、node.js
中間件代理跨域、後端在頭部信息設置安全域名、後端在服務器上設置cors
。
ps:有三個標籤容許跨域加載資源: <img src=xxx> <link href = xxx> <script src=xxx>
三個標籤場景: <img>
用於打點統計,統計網站多是其餘域 <link> <script>
可使用CDN
,CDN
的也是其餘域 <script>
能夠用於JSONP
⚠️跨域注意事項
全部的跨域請求都必須通過信息提供方容許
若是未經容許便可獲取,那麼瀏覽器同源策略出現漏洞
XML
和JSON
的區別?數據體積方面 JSON
相對於XML
來說,數據的體積小,傳遞的速度更快些。
數據交互方面 JSON
與JavaScript
的交互更加方便,更容易解析處理,更好的數據交互
數據描述方面 JSON
對數據的描述性比XML
較差
傳輸速度方面 JSON
的速度要遠遠快於XML
get
和post
的區別一、get
和post
在HTTP
中都表明着請求數據,其中get請求相對來講更簡單、快速,效率高些
二、get
相對post
安全性低
三、get
有緩存,post
沒有
四、get
體積小,post
能夠無限大
五、get
的url
參數可見,post
不可見
六、get
只接受ASCII
字符的參數數據類型,post
沒有限制
七、get
請求參數會保留歷史記錄,post
中參數不會保留
八、get
會被瀏覽器主動catch,post
不會,須要手動設置
九、get
在瀏覽器回退時無害,post
會再次提交請求
何時使用post
?
post
通常用於修改服務器上的資源,對所發送的信息沒有限制。好比
一、沒法使用緩存文件(更新服務器上的文件或數據庫)
二、向服務器發送大量數據(POST
沒有數據量限制)
三、發送包含未知字符的用戶輸入時,POST
比 GET
更穩定也更可靠
TCP
創建鏈接爲何須要三次?TCP
協議的通訊雙方, 都必須維護一個序列號, 以標識發送出去的數據包中, 哪些是已經被對方收到的。 三次握手的過程便是通訊雙方相互告知序列號起始值, 並確認對方已經收到了序列號起始值的必經步驟ES5
的繼承和ES6
的繼承有什麼區別?ES5
的繼承時經過prototype
或構造函數機制來實現。ES5
的繼承實質上是先建立子類的實例對象,而後再將父類的方法添加到this
上(Parent.apply(this)
)。
ES6
的繼承機制徹底不一樣,實質上是先建立父類的實例對象this
(因此必須先調用父類的super()
方法),而後再用子類的構造函數修改this
。
具體的:ES6
經過class
關鍵字定義類,裏面有構造方法,類之間經過extends
關鍵字實現繼承。子類必須在constructor
方法中調用super
方法,不然新建實例報錯。由於子類沒有本身的this
對象,而是繼承了父類的this
對象,而後對其進行加工。若是不調用super
方法,子類得不到this
對象。
ps:super
關鍵字指代父類的實例,即父類的this
對象。在子類構造函數中,調用super
後,纔可以使用this
關鍵字,不然報錯
javascript
如何實現繼承?一、構造繼承
二、原型繼承
三、實例繼承
四、拷貝繼承
原型prototype
機制或apply和call
方法去實現較簡單,建議使用構造函數與原型混合方式
function Parent(){
this.name = 'wang';
}
function Child(){
this.age = 28;
}
Child.prototype = new Parent();//繼承了Parent,經過原型
var demo = new Child();
alert(demo.age);
alert(demo.name);//獲得被繼承的屬性
}
複製代碼
ES6
的理解新增模板字符串(爲JavaScript
提供了簡單的字符串插值功能)
箭頭函數 for-of
(用來遍歷數據—例如數組中的值。) arguments
對象可被不定參數和默認參數完美代替。 ES6
將promise
對象歸入規範,提供了原生的Promise
對象。
增長了let和const
命令,用來聲明變量。
增長了塊級做用域。 let
命令實際上就增長了塊級做用域。
還有就是引入module
模塊的概念
this
對象,就是定義時所在的對象,而不是使用時所在的對象new
命令,不然會拋出一個錯誤arguments
對象,該對象在函數體內不存在。若是要用,能夠用Rest
參數代替yield
命令,所以箭頭函數不能用做Generator
函數forEach、for in、for of
三者區別forEach
更多的用來遍歷數 for in
通常經常使用來遍歷對象或json
for of
數組對象均可以遍歷,遍歷對象須要經過和Object.keys()
for in
循環出的是key,for of
循環出的是value
Set、Map
的區別應用場景Set
用於數據重組,Map用於數據儲存
Set:
1,成員不能重複
2,只有鍵值沒有鍵名,相似數組
3,能夠遍歷,方法有add, delete,has
Map:
1,本質上是健值對的集合,相似集合
2,能夠遍歷,能夠跟各類數據格式轉換
promise
對象的用法,手寫一個promise
promise
是一個構造函數,下面是一個簡單實例
var promise = new Promise((resolve,reject) => {
if (操做成功) {
resolve(value)
} else {
reject(error)
}
})
promise.then(function (value) {
// success
},function (value) {
// failure
})
複製代碼
Promise
的使用場景,'Promise
'它所解決的問題以及如今對於異步操做的解決方案。Promise
的使用場景:ajax
請求,回調函數,複雜操做判斷。 Promise
是ES6
爲了解決異步編程所誕生的。
異步操做解決方案:Promise、Generator
、定時器(不知道算不算)、還有ES7
的async
ECMAScript6
怎麼寫class
,爲何會出現class
這種東西?這個語法糖可讓有OOP
基礎的人更快上手js
,至少是一個官方的實現了 但對熟悉js
的人來講,這個東西沒啥大影響;一個Object.creat()
搞定繼承,比class
簡潔清晰的多
每次比較相鄰的兩個數,若是後一個比前一個小,換位置
var arr = [3, 1, 4, 6, 5, 7, 2];
function bubbleSort(arr) {
for (var i = 0; i < arr.length - 1; i++) {
for(var j = 0; j < arr.length - i - 1; j++) {
if(arr[j + 1] < arr[j]) {
var temp;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
console.log(bubbleSort(arr));
複製代碼
採用二分法,取出中間數,數組每次和中間數比較,小的放到左邊,大的放到右邊
var arr = [3, 1, 4, 6, 5, 7, 2];
function quickSort(arr) {
if(arr.length == 0) {
return []; // 返回空數組
}
var cIndex = Math.floor(arr.length / 2);
var c = arr.splice(cIndex, 1);
var l = [];
var r = [];
for (var i = 0; i < arr.length; i++) {
if(arr[i] < c) {
l.push(arr[i]);
} else {
r.push(arr[i]);
}
}
return quickSort(l).concat(c, quickSort(r));
}
console.log(quickSort(arr));
複製代碼
<img id="img1" src="preview.png" data-realsrc = "abc.png"/>
<script type = "text/javascript">
var img1 = document.getElementById("img1")
img1.src = img1.getAttribute('data-realsrc')
</script>
複製代碼
DOM
查詢// 未緩存 DOM查詢
var i
for (i = 0; i < document.getElementByTagName('p').length; i++) {
//todo
}
//緩存了DOM查詢
var pList = document.getElementByTagName('p')
var i
for (i= 0; i < pList.length; i++) {
// todo
}
複製代碼
DOM
插入var listNode = document.getElementById('list')
//要插入10個li標籤
var frag = document.createDocumentFragment();
var x,li
for (x = 0; x < 10; x++) {
li = document.createElement('li')
li.innerHTML = "List item" + x
frag.appendChild(li)
}
listNode.appendChild(frag)
複製代碼
var textarea = document.getElementById('text')
var timeoutId
textarea.addEventListener('keyup', function () {
if (timeoutId) {
clearTimeout(timeoutId)
}
timeoutId = setTimeout(function () {
//觸發事件
},100)
})
複製代碼
window.addEventListener('load', function () {
//頁面的所有資源加載完纔會去執行,包括圖片,視頻
})
document.addEventListener('DOMContentLoaded', function() {
//DOM 渲染完便可執行,此時圖片,視頻還可能沒有加載完成
})
複製代碼
首先能夠經過 Object.assign
來解決這個問題
let a = {
age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1
複製代碼
這個問題一般能夠經過JSON.parse(JSON.stringify(object))
來解決
let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE
複製代碼
[1, [2], 3].flatMap(v => v)
// -> [1, 2, 3]
複製代碼
若是想將一個多維數組完全的降維,能夠這樣實現
const flattenDeep = (arr) => Array.isArray(arr)
? arr.reduce( (a, b) => [...a, ...flattenDeep(b)] , [])
: [arr]
flattenDeep([1, [[2], [3, [4]], 5]])
複製代碼
在開發中,可能會遇到這樣的狀況。有些資源不須要立刻用到,可是但願儘早獲取,這時候就可使用預加載 預加載實際上是聲明式的 fetch
,強制瀏覽器請求資源,而且不會阻塞 onload
事件,可使用如下代碼開啓預加載
<link rel="preload" href="http://example.com">
複製代碼
預加載能夠必定程度上下降首屏的加載時間,由於能夠將一些不影響首屏但重要的文件延後加載,惟一缺點就是兼容性很差
能夠經過預渲染將下載的文件預先在後臺渲染,可使用如下代碼開啓預渲染
<link rel="prerender" href="http://poetries.com">
複製代碼
一、儘量把 <script> 標籤放在 body 以後,避免 JS 的執行卡住 DOM 的渲染,最大程度保證頁面儘快地展現出來
二、儘量合併 JS 代碼:提取公共方法,進行面向對象設計等……
三、CSS 能作的事情,儘可能不用 JS 來作,畢竟 JS 的解析執行比較粗暴,而 CSS 效率更高。
四、儘量逐條操做 DOM,並預約好 CSs 樣式,從而減小 reflow 或者 repaint 的次數。
五、儘量少地建立 DOM,而是在 HTML 和 CSS 中使用 display: none 來隱藏,按需顯示。
六、壓縮文件大小,減小資源下載負擔。
複製代碼
一、不要在同一行聲明多個變量
二、請使用===/!==來比較true/false或者數值
三、使用對象字面量替代new Array這種形式
四、不要使用全局變量
五、Switch語句必須帶有default分支
六、函數不該該有時候有返回值,有時候沒有返回值
七、For循環必須使用大括號
八、IF語句必須使用大括號
九、for-in循環中的變量 應該使用var關鍵字明確限定做用域,從而避免做用域污染
複製代碼