24 、GET系列和POST系列的本質區別 ?javascript
xhr.open('GET','/list?name=zhufeng&year=10&xxx=xxx...')
xhr.send('....') 請求主體中傳遞的內容理論上沒有大小限制,可是真實項目中,爲了保證傳輸的速度,咱們會本身限制一些
複製代碼
//=>解決辦法設置隨機數
xhr.open('GET','/list?name=zhufeng&_='+Math.random());
...
xhr.open('GET','/list?name=zhufeng&_='+Math.random());
複製代碼
2三、Http 狀態碼 301 和 302 的應用場景分別是什麼html
301重定向是永久的重定向,搜索引擎在抓取新的內容的同時也將舊的網址替換爲了重定向以後的網址。java
302重定向只是暫時的重定向,搜索引擎會抓取新的內容而保留舊的地址,由於服務器返回302,因此,搜索搜索引擎認爲新的網址是暫時的。git
2二、函數的防抖節流有什麼區別,怎麼實現? 參考另外一篇文章 juejin.im/post/5d65cb…es6
2一、獲取數組中的最大值和最小值, 你有幾種辦法github
let ary = [12, 24, 13, 8, 35, 15];
/* 解決方案一:先排序,第一項和最後一項就是咱們須要的 */
ary.sort(function (a, b) {
return a - b;
});
let min = ary[0];
let max = ary[ary.length - 1];
console.log(min, max);
============
// 解決方案二: Math.max/Math.min
//=>Math.max/min要求咱們傳遞的數據是一項項傳遞進來,獲取一堆數中的最大最小,而不是獲取一個數組中的最大最小
let min = Math.min([12, 24, 13, 8, 35, 15]);
console.log(min);//=>NaN
let min = Math.min(12, 24, 13, 8, 35, 15);
console.log(min); //=>8
1.基於ES6的展開運算符
let min = Math.min(...ary);
2.利用apply來實現便可(this無所謂,主要是利用apply給函數傳參,須要寫成一個數組的特徵)
let min = Math.min.apply(Math, ary);
/* 解決方案三:假設法(假設第一個是最大的,讓數組中的每一項分別和當前假設的值比較,若是比假設的值大,則把最大的值設爲新的假設值,繼續向後比較便可) */
let max = ary[0];
/* for (let i = 1; i < ary.length; i++) { let item = ary[i]; item > max ? max = item : null; } */
ary.forEach(item => {
item > max ? max = item : null;
});
console.log(max); //=>35
複製代碼
一、JS中的數據類型都有哪些?它們之間有什麼區別?該如何檢測?web
@數據類型算法
- 基本數據類型: number、string、boolean、null、undefined
- 引用數據類型: object(普通對象、數組對象、正則對象、日期對象、Math、實例、 prototype等)
- function (普通函數和類)
- 特殊數據類型:Symbol
@區別
基本數據類型按值操做 , 引用數據類型按照堆內存的引用地址來操做編程@數據類型檢測四種方式
typeof、instanceof、constructor、Object.prototype.toString.call()數組
二、經常使用瀏覽器的內核都有哪些?
webkit、Gecko、Trident、Presto等
三、數組中經常使用的迭代方法有哪些?都是什麼意思?(至少四種)
forEach、map、find、some、filter、reduce、every、sort等
四、闡述一下let/var/const三者之間的區別?
let 和 var 的區別
- 不存在變量提高
- 不容許重複聲明
- 在全局做用域下設置變量不會給window設置屬性
- 存在塊級做用域
- 解決了一些暫時性死區問題
let 和 const 的區別
const 建立的是常量,存儲的值不能被修改(準確說是不能修改變量的指 向)
五、闡述一下call/apply/bind三者之間的區別,以及應用場景?
一、 Function.prototype.apply和Function.prototype.call 的做用是同樣的,區別在於傳入參數的不一樣;
- 第一個參數:都是指定函數體內this的指向;
- 第二個參數:開始不一樣
- apply:數組或者類數組;
- call: 從第二個開始傳入的參數是不固定的;
二、call 和 bind 的區別 call在改變函數this指向的時候,會把函數當即執行,而bind不會把函數立 即執行,只是預先處理了this和實參信息;
三、call比apply的性能要好,日常能夠多用call , call傳入參數的格式正是內部所須要的格式,尤爲是es6 引入了 Spread operator (延展操做符) 後,即便參數是數組,可使用 call;
參考[call和apply的性能對比] (github.com/noneven/__/…)四、真實項目中,咱們須要改變this指向的時候,會應用這三個方法,例如:
- 給元素進行事件綁定,咱們須要把事件觸發,所執行的函數中this和參數進 行預先處理,此時可使用bind進行處理;
- 咱們能夠基於call方法,讓類數組借用數組原型上的方法,例如:把類數組 轉換爲數組
- 能夠基於apply傳參是一個數組,借用Math.max獲取數組中的最大值 ......
六、window.onload VS $(document).ready()
1.$(document).ready() 採用的是DOM2事件綁定,監聽的是DOMContentLoaded這個事件,因此只要DOM結構加載完成就會被觸發執行,並且同一個頁面中可使用屢次(綁定不一樣的方法,由於基於DOM2事件池綁定機制完成的)
2.window.onload必須等待全部資源都加載完成纔會被觸發執行,採用DOM0事件綁定,同一個頁面只能綁定一次(一個方法),想綁定多個也須要改成window.addEventListener('load', function () {})DOM2綁定方式
七、.有A和B兩個開發者,他們同時開發一款產品(最後的代碼須要合併),爲了防止相互以前產生變量污染,他們決定採用高級單例模式來進行模塊化開發,請編寫相應的代碼示例!
// 開發者A
let AModule = (function () {
let n = 10;
let query = function () {
//...
};
let fn = function () {
//...
//調取開發者B編寫的QUERY方法
BModule.query();
};
return {
query: query,
init: function () {
query();
fn();
}
}
})();
// 開發者B
let BModule = (function () {
let n = 20;
let query = function () {
//...
};
let sum = function () {
//...
//調取開發者A編寫的QUERY方法
AModule.query();
};
return {
query,
init: function () {
query();
sum();
}
}
})();
AModule.init();
BModule.init();
複製代碼
七、ES6中的新語法規範
* let / const
* class 建立類
* import / export :ES6 Module 模塊的導入導出規範(JS中的模塊化規範 AMD ->
CMD -> CommonJS -> ES6 Module)
* Arrow Function 箭頭函數
* 模板字符串
* 解構賦值
* '...'拓展、展開、剩餘運算符
* Promise / async / await
* for of循環
* Set / Map
* Array / Object ... 提供的新方法
複製代碼
八、箭頭函數與普通函數(function)的區別是什麼?構造函數(function)可使用 new 生成實例,那麼箭頭函數能夠嗎?爲何?
箭頭函數
- 語法上比普通函數更加簡潔;
- 沒有ARGUMENTS,能夠藉助(...res)實現,而且接收值爲數組;
- 沒有本身的THIS,定義時所在的THIS;
不可使用 new 命令:**
- 箭頭函數沒有THIS,
- 沒有prototype屬性,而NEW命令在執行的時候須要將構造函數的prototype賦值給新對象的__proto__
let Fn = () =>{
this.x = 200;
}
let f = new Fn; // Uncaught TypeError: Fn is not a constructor
複製代碼
八、怎麼讓一個 div 水平垂直居中?(很多於三種解決方案)
/* 已知寬高 */
.box {
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px; (減去盒子的一半)
margin-left: -50px;
width: 100px;
height: 100px;
}
========================
/* 未知寬高 */
.box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
==========================
.box {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
===============================
[父級] {
display: flex;
justify-content: center;
align-items: center;
}
複製代碼
九、實現 (5).add(3).minus(2) ,使其輸出結果爲:6
// 每次方法執行完,都要返回NUMBER這個類的實例,這樣才能夠繼續調取NUMBER類原型中的方法(鏈式寫法);
~function () {
// 保證傳入值爲數字
function check(n) {
n = Number(n);
return isNaN(n) ? 0 : n;
};
function add(n) {
n = check(n);
return this + n;
};
function minus(n) {
n = check(n);
return this - n;
}
["add", "minus"].forEach(item => {
Number.prototype[item] = eval(item);
});
}();
let res = (5).add(3).minus(2);
console.log(res); // => 6
複製代碼
十、如何把一個字符串的大小寫取反(大寫變小寫小寫變大寫),例如 ’AbC' 變成 'aBc' **
let str = 'JinTianTIanQiHenhao';
str = str.replace(/[a-zA-Z]/g, content => {
//content:每一次正則匹配到的結果;
// 驗證是否大寫字母,統一轉換成大寫,再跟以前的字母對比,若是同樣,說明以前也是大寫;
// 在ASCII 表中找到大寫字母的取值範圍進行判斷(65-90);
return content.toUpperCase() === content ? content.toLowerCase() : content.toUpperCase();
});
console.log(str) // =>'jINtIANtiANqIhENHAO'
複製代碼
十、實現一個字符串匹配算法,從字符串 S 中,查找是否存在字符串 T,若存在返回所在位置,不存在返回-1!(若是不能基於indexOf/includes等內置的方法,你會如何處理呢?
/* S: 查找S中T是否存在 pramas: [T] =>須要查找的字符串內容; return:存在返回其索引,不存在返回-1; */
// 循環原始字符串中每一項,讓每一項從當前位置向後截取 T.length個字符,
// 而後和T進行比較,若是不同繼續循環;若是同樣返回當前索引便可;
// THIS:S =>原字符串;
// pramas: [T]=> 需查找的字符串;
// return: 匹配完整字符串開始的索引;
~function () {
function myIndexOf(T) {
let lenT = T.length,
lenS = S.length,
res = -1;
if (lenS < lenT) return null;
for (let i = 0; i < lenS - lenT; i++) {
if(this.substr(i, lenT) === T){
res = i;
break; // 爲了不出現多個符合,找最後一個,讓其找到一個就結束;
};
};
return res;
};
String.prototype.myIndexOf = myIndexOf;
}();
let S = 'jingerzitiantianqihenhao',
T = 'tian';
let res = S.myIndexOf(T);
console.log(res);
=========第二種=========
**使用正則匹配**
~function () {
function myIndexOf(T) {
let reg = new RegExp(T),
res = reg.exec(this);
return res === null ? -1 : res.index;
}
String.prototype.myIndexOf = myIndexOf;
}();
let S = 'jingerzitianqihenhao',
T = 'tian';
let res = S.myIndexOf(T);
console.log(res);
複製代碼
十一、在輸入框中如何判斷輸入的是一個正確的網址,例如:用戶輸入一個字符串,驗證是否符合URL網址的格式
/* 在輸入框中如何判斷輸入的是一個正確的網址,例如:用戶輸入一個字符串,驗證是否符合URL網址的格式 */
//=>URL格式
//1.協議:// http/https/ftp
//2.域名
// www.sina.cn
// sina.cn
// kbs.sports.qq.com
// kbs.sports.qq.com.cn
//3.請求路徑
// /
// /index.html
// /stu/index.html
// /stu/
//4.問號傳參
// ?xxx=xxx&xxx=xxx
//5.哈希值
// #xxx
let str = "https://www.sina.com.cn";
let reg = /^(?:(http|https|ftp):\/\/)?((?:[\w-]+\.)+[a-z0-9]+)((?:\/[^/?#]*)+)?(\?[^#]+)?(#.+)?$/i;
console.log(reg.exec(str));
複製代碼
十二、編寫一條正則,用來驗證此規則:一個6~16位的字符串,必須同時包含有大小寫字母和數字
let reg = /(?!^[a-zA-Z]+$)(?!^[A-Z0-9]+$)(?!^[a-z0-9]+$)^[a-zA-Z0-9]{6,16}$/;
複製代碼
1三、英文字母漢字組成的字符串,用正則給英文單詞先後加空格
let str = "no做no死,你能你can!",
reg = /\b[a-z]+\b/ig;
str = str.replace(reg, value => {
return " " + value + " ";
}).trim();//=>String.prototype.trim/.trimLeft/.trimRight 去除字符串首尾空格
console.log(str);
複製代碼
1四、改造下面代碼,使之輸出0-9
for (var i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i);
}, 1000);
}
//=>定時器是異步編程:每一輪循環設置定時器,無需等定時器觸發執行,繼續下一輪循環(定時器觸發的時候,循環已經結束了)
=============第一種============
//=>LET存在塊級做用域,每一次循環都會在當前塊做用域中造成一個私有變量i存儲0~9
//當定時器執行的時候,所使用的i就是所處塊做用域中的i
for (let i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i);
}, 1000);
}
============第二種=============
for (var i = 0; i < 10; i++) {
~function(i){
setTimeout(() => {
console.log(i);
}, 1000);
} (i)
}
============第三種=============
for (var i = 0; i < 10; i++) {
setTimeout((i => () => console.log(i))(i), 1000);
}
==============
=>能夠基於bind的預先處理機制:在循環的時候就把每次執行函數須要輸出的結果,預先傳給函數便可
var fn = function (i) {
console.log(i);
};
for (var i = 0; i < 10; i++) {
setTimeout(fn.bind(null, i), 1000);
}
複製代碼
1五、下面代碼輸出的結果是多少,爲何?如何改造一下,就能讓其輸出 20 10?
var b = 10;
(function b() {
b = 20;
console.log(b);
})();
console.log(b);
---
var b = 10;
(function b() {
b = 20;
console.log(b); //=>函數b
})();
console.log(b); //=>10
let fn = function AAA() {
// "use strict";
// AAA = 1000; //=>Uncaught TypeError: Assignment to constant variable.
console.log(AAA); //=>當前函數
};
// AAA(); //=>Uncaught ReferenceError: AAA is not defined
// 1.本應匿名的函數若是設置了函數名,在外面仍是沒法調用,可是在函數裏面是可使用的
// 2.並且相似於建立常量同樣,這個名字存儲的值不能再被修改(非嚴格模式下不錯報,可是不會有任何的效果,嚴格模式下直接報錯,咱們能夠把AAA理解爲是用 const 建立出來的)
fn(); */
=========================
var b = 10;
(function b(b) {
b = 20;
console.log(b); //=>20 裏面的b必定須要是私有的,不能是全局的(聲明它或者改成形參)
})();
console.log(b); //=>10
複製代碼
1六、下面代碼a在什麼值狀況下會輸出1
var a = ?;
if (a == 1 && a == 2 && a == 3) {
console.log(1);
}
-----------
== 相對相等,若是左右兩邊數據類型不同,則先轉換爲相同的數據類型,而後在進行比較
* 1. {}=={} 兩個對象進行比較,比較的是堆內存的地址
* 2. null==undefined 相等的 / null===undefined 不相等
* 3. NaN==NaN 不相等 NaN和誰都不相等
* 4. [12]=="12" 對象和字符串比較,是把對象toString()轉換爲字符串後再進行比較的
* 5. 剩餘全部狀況在進行比較的時候,都是轉換爲數字(前提數據類型不同)
* 對象轉數字:先轉換爲字符串,而後再轉換爲數字
* 字符串轉數字:只要出現一個非數字字符,結果就是NaN
* 布爾轉數字:true->1 false->0
* null轉數字0
* undefined轉數字NaN
=======第一種========
// =>對象和數字比較:先把對象.toString()變爲字符串,而後再轉換爲數字
a.toString(); //=>此時調取的就再也不是Object.prototype.toString了,調取的是本身私有的
var a = {
n: 0,
toString() {
return ++this.n;
}
}
=========第二種========
//=>shift:刪除數組第一項,把刪除的內容返回,原有數組改變
// 調取toString === a.shift;
let a = [1, 2, 3];
a.toString = a.shift;
=========第三種=========
// ES6中新增長的一些方法
// Object.defineProperty屬性,執行window.a的時候,會先執行get這個函數,因此在get這個函數編寫代碼便可;
Object.defineProperty(window, 'a', {
get: function () {
//=>this:window.a => undefined;
this.value ? this.value++ : this.value = 1;
return this.value;
}
});
複製代碼
1七、下面代碼的輸出結果?爲何?
let obj = {
2: 3,
3: 4,
length: 2,
push: Array.prototype.push
}
obj.push(1);
obj.push(2);
console.log(obj);
// ---------------------------------
// => Array.prototype.push方法;
Array.prototype.push = function (...res) {
res.forEach(item=>{
this[this.length] = item;
})
return this.length;
};
let arr = [1,2,3];
arr.push(1,'d',9,'hha',function(){});
console.log(arr.push(1,'d',9,'hha',function(){})) // 8
console.log(arr); // [1, 2, 3, 1, "d", 9, "hha", ƒ]
//=============
/obj.push(1); obj[obj.length] = 1 => obj[2] = 1
// 結果
obj = {
2: 1,
3: 4,
length: 2,
push: Array.prototype.push
}
/obj.push(2); obj[3] = 2 => obj[2] = 2
// 結果
obj = {
2: 1,
3: 2,
length: 2,
push: Array.prototype.push
}
複製代碼
1八、完成以下需求
/* 某公司1到12月份的銷售額存在一個對象裏面 以下: { 1: 222, 2: 123, 5: 888 }, 請把數據處理爲以下結構:[222, 123, null, null, 888, null, null, null, null, null, null, null] */
//=======第一種=======
let obj = {
1: 222,
2: 123,
5: 888
};
let ary = new Array(12).fill(null).map((item,index) => {
return obj[index+1] || item;
});
console.log(ary) // [222, 123, null, null, 888, null, null, null, null, null, null, null];
//========第二種========
let obj = {
1: 222,
2: 123,
5: 888
};
obj.length = 13;
let ary = Array.from(obj).slice(1).map(item => {
return typeof item === "undefined" ? null : item;
})
console.log(ary) // [222, 123, null, null, 888, null, null, null, null, null, null, null];
//=======第三種 =====
let obj = {
1: 222,
2: 123,
5: 888
};
// =>Object.keys(obj):獲取obj中全部的屬性名,以數組的方式返回
let arr = Object.keys(obj);
console.log(arr); //["1", "2", "5"]
let ary = new Array(12).fill(null);
arr.forEach(item =>{
ary[item - 1] = obj[item];
})
console.log(ary) // [222, 123, null, null, 888, null, null, null, null, null, null, null]
複製代碼
1九、給定兩個數組, 寫一個方法來計算它們的交集
et nums1 = [12, 23, 34, 23, 45, 34, 25, 46, 35];
let nums2 = [10, 35, 24, 23, 36, 47, 56];
//=> 輸出結果 [22.23.25]
===========第一種==========
let arr = [];
nums1.forEach((item, index) => {
let n = nums2.indexOf(item);
if (n >= 0){
arr.push(item);
nums1.splice(index,1);
nums1.splice(n,1);
}
});
console.log(arr) // [22.23.25]
==========第二種==========
let arr = [];
for (let i = 0; i < nums1.length; i++) {
let item1 = nums1[i];
for (let k = 0; k < nums2.length; k++) {
let item2 = nums2[k];
if (item1 === item2) {
arr.push(item1);
break;
}
}
}
console.log(arr);
複製代碼
20、算法題「旋轉數組」
/* 給定一個數組,將數組中的元素向右移動 k 個位置,其中 k 是非負數 輸入: [1, 2, 3, 4, 5, 6, 7] 和 k = 3 輸出: [5, 6, 7, 1, 2, 3, 4] 解釋: 向右旋轉 1 步: [7, 1, 2, 3, 4, 5, 6] 向右旋轉 2 步: [6, 7, 1, 2, 3, 4, 5] 向右旋轉 3 步: [5, 6, 7, 1, 2, 3, 4] 輸入: [-1, -100, 3, 99] 和 k = 2 輸出: [3, 99, -1, -100] 解釋: 向右旋轉 1 步: [99, -1, -100, 3] 向右旋轉 2 步: [3, 99, -1, -100] */
========第一種=========
let arr = [1, 2, 3, 4, 5, 6, 7];
function change(k) {
if (k < 0 && k === this.length && k > this.length) return;
if (k > this.length) return k = k % this.length;
return this.slice(-k).concat(this.slice(0, this.length - k));
// return [...this.splice(this.length-k),...this];
}
Array.prototype.change = change;
let ary = arr.change(3);
console.log(ary); // [5, 6, 7, 1, 2, 3, 4]
=========第二種========
function change(k) {
//=>參數處理
if (k < 0 || k === 0 || k === this.length) return this;
if (k > this.length) k = k % this.length;
// for (let i = 0; i < k; i++) {
// this.unshift(this.pop());
// }
new Array(k).fill('').forEach(() => this.unshift(this.pop()));
return this;
}
Array.prototype.change = change;
let ary = arr.change(3);
console.log(ary); // [5, 6, 7, 1, 2, 3, 4]
複製代碼