1. 數組方法、reduce()的第二個參數
reduce() MDN文檔
- accumulator 累計器
- currentValue 當前值
- currentIndex 當前索引
- array 數組
- 在沒有初始值的空數組上調用 reduce 將報錯(如果有initialValue不報錯)。
- 回調函數第一次執行時,accumulator 和currentValue的取值有兩種情況:如果調用reduce()時提供了initialValue,accumulator取值為initialValue,currentValue取數組中的第一個值;如果沒有提供 initialValue,那么accumulator取數組中的第一個值,currentValue取數組中的第二個值。
- 如果沒有提供initialValue,reduce 會從索引1的地方開始執行 callback 方法,跳過第一個索引。如果提供initialValue,從索引0開始。
- 如果數組為空且沒有提供initialValue,會拋出TypeError 。如果數組僅有一個元素(無論位置如何)并且沒有提供initialValue, 或者有提供initialValue但是數組為空,那么此唯一值將被返回并且callback不會被執行。
[0, 1, 2, 3, 4].reduce((prev, curr) => prev + curr );
2. sort方法的回調,可以return true或false嗎 正 負 零
MDN sort()
sort方法改變原數組
function compare(a, b) {if (a < b ) { return -1;}if (a > b ) {return 1;}return 0;
}
簡化
numbers.sort(function(a, b) {return a - b;
});
var arr = [1, 56, -45, 4]
var newArr = arr.sort(function(a,b) {if (a > b) {return true} else if (a < b) {return -1} else {return false}}
)
console.log('升序', newArr)
不提供回調時
回調函數(比較函數):用來指定按某種順序進行排列的函數。如果省略,元素按照轉換為的字符串的各個字符的Unicode位點進行排序。
因此,并非所有arr.sort() 的結果都是亂序
- 如果 compareFunction(a, b) 小于 0 ,那么 a 會被排列到 b 之前;
- 如果 compareFunction(a, b) 等于 0 , a 和 b 的相對位置不變。
- 如果 compareFunction(a, b) 大于 0 , b 會被排列到 a 之前。
- compareFunction(a, b) 必須總是對相同的輸入返回相同的比較結果,否則排序的結果將是不確定的。隨機排序
var arr = [1, 56, -45, 4]
var newArr = arr.sort((a, b) => {return Math.random(1) - 0.5}
)
console.log('隨機', newArr)
不會改變原來數組的有:
concat()—連接兩個或更多的數組,并返回結果。
every()—檢測數組元素的每個元素是否都符合條件。
some()—檢測數組元素中是否有元素符合指定條件。
filter()—檢測數組元素,并返回符合條件所有元素的數組。
indexOf()—搜索數組中的元素,并返回它所在的位置。
join()—把數組的所有元素放入一個字符串。
toString()—把數組轉換為字符串,并返回結果。
lastIndexOf()—返回一個指定的字符串值最后出現的位置,在一個字符串中的指定位置從后向前搜索。
map()—通過指定函數處理數組的每個元素,并返回處理后的數組。
slice()—選取數組的的一部分,并返回一個新數組。
valueOf()—返回數組對象的原始值。
--------------------------------------------分割線----------------------------------------------------
會改變原來數組的有:4+1+1+1
pop()—刪除數組的最后一個元素并返回刪除的元素。
push()—向數組的末尾添加一個或更多元素,并返回新的長度。
shift()—刪除并返回數組的第一個元素。
unshift()—向數組的開頭添加一個或更多元素,并返回新的長度。
reverse()—反轉數組的元素順序。
sort()—對數組的元素進行排序。
splice()—用于插入、刪除或替換數組的元素。
3. const聲明的數組,可以修改嗎
數組是引用類型
const聲明的引用類型變量,不可以變的是變量引用始終指向某個對象,不能指向其他對象,但是所指向的某個對象本身是可以變的。
阮一峰 ES6 let和const聲明變量
3.1 let
- let聲明的變量,只在let命令所在的代碼塊內有效。出了
{}
使用報錯 - for循環的計數器,就很合適使用let命令。當前的i只在本輪循環有效,所以每一次循環的i其實都是一個新的變量。 JavaScript 引擎內部會記住上一輪循環的值,初始化本輪的變量i時,就在上一輪循環的基礎上進行計算。從而能計算出本輪循環的值。
- for循環還有一個特別之處,就是設置循環變量的那部分是一個父作用域,而循環體內部是一個單獨的子作用域。
- ES5“變量提升”現象,即變量可以在聲明之前使用,值為undefined。這種現象多多少少是有些奇怪的。
- 為了糾正這種現象,let命令改變了語法行為,它所聲明的變量一定要在聲明后使用,否則報錯。
- 暫存性死區:只要塊級作用域內存在let命令,它所聲明的變量就“綁定”(binding)這個區域,不再受外部的影響。使用let命令聲明變量之前,該變量都是不可用的。
- 在沒有let之前,typeof運算符是百分之百安全的,永遠不會報錯。現在這一點不成立了。這樣的設計是為了讓大家養成良好的編程習慣,變量一定要在聲明之后使用,否則就報錯。
- 總之,暫時性死區的本質就是,只要一進入當前作用域,所要使用的變量就已經存在了,但是不可獲取,只有等到聲明變量的那一行代碼出現,才可以獲取和使用該變量。
- let不允許在相同作用域內,重復聲明同一個變量。
- ES5 只有全局作用域和函數作用域,沒有塊級作用域,這帶來很多不合理的場景:內層變量可能會覆蓋外層變量;用來計數的循環變量泄露為全局變量。
- let實際上為 JavaScript 新增了塊級作用域。塊級作用域的出現,實際上使得獲得廣泛應用的匿名立即執行函數表達式(匿名 IIFE)不再必要了。
- 考慮到環境導致的行為差異太大,應該避免在塊級作用域內聲明函數。如果確實需要,也應該寫成函數表達式,而不是函數聲明語句。
- 每一次循環的i其實都是一個新的變量
var a = [];
for (let i = 0; i < 10; i++) {a[i] = function () {console.log(i);};
}
a[6](); // 6
- 函數內部的變量i與循環變量i不在同一個作用域,有各自單獨的作用域
for (let i = 0; i < 3; i++) {let i = 'abc';console.log(i);
}
// abc
// abc
// abc
- 使用let命令聲明之前,該變量都是不可用的
if (true) {// TDZ開始tmp = 'abc'; // ReferenceErrorconsole.log(tmp); // ReferenceErrorlet tmp; // TDZ結束console.log(tmp); // undefinedtmp = 123;console.log(tmp); // 123
}
- typeof
typeof x; // ReferenceError
let x;
- 隱蔽的死區
下面代碼中,調用bar函數之所以報錯(某些實現可能不報錯),是因為參數x默認值等于另一個參數y,而此時y還沒有聲明,屬于“死區”。如果y的默認值是x,就不會報錯,因為此時x已經聲明了。
function bar(x = y, y = 2) {return [x, y];
}bar(); // 報錯
- 不允許重復聲明
function func(arg) {let arg;
}
func() // 報錯function func(arg) {{let arg;}
}
func() // 不報錯
- ES5變量提升
var tmp = new Date();
function f() {console.log(tmp);if (false) {var tmp = 'hello world';}
}
f(); // undefined
3.2 const 只讀常量
- const實際上保證的,并不是變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動。對于簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,因此等同于常量。但對于復合類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個指向實際數據的指針,const只能保證這個指針是固定的(即總是指向另一個固定的地址),至于它指向的數據結構是不是可變的,就完全不能控制了。因此,將一個對象聲明為常量必須非常小心。
- 凍結對象
const foo = Object.freeze({});// 常規模式時,下面一行不起作用;
// 嚴格模式時,該行會報錯
foo.prop = 123;
- 徹底凍結對象(遞歸)
var constantize = (obj) => {Object.freeze(obj);Object.keys(obj).forEach( (key, i) => {if ( typeof obj[key] === 'object' ) {constantize( obj[key] );}});
};
4. 前后端項目上線部署 nginx
4.1 輕量級高并發服務器nginx
終于有人把 Nginx 說清楚了,圖文詳解!
4.2 跨域
vue+nginx設置跨域
4.2.1 vue-cli配置
這篇寫得最清楚
【踩坑+實戰】vue+axios使用代理解決跨域問題
dev: {proxyTable: {//使用proxyTable進行跨域設置'/api': { //使用"/api"來代替"https://www.easy-mock.com/mock/5d4b7d772b863e1413ad66ab/iVP/" target: 'https://www.easy-mock.com/mock/5d4b7d772b863e1413ad66ab/iVP/', //源地址 ,注意‘/’是否對應changeOrigin: true, //改變源,是否跨域pathRewrite: {// 這里理解成用'/api'代替target里面的地址,后面組件中我們掉接口時直接用api代替 // 比如我要調用'http://www.abc.com/user/add',直接寫'/api/user/add'即可''^/api': '' //路徑重寫,也可以寫成 '^/api': 'https://www.easy-mock.com/mock/5d4b7d772b863e1413ad66ab/iVP/'}}}
- 注意: 以上設置只能在開發環境下使用,打包后會出現路徑問題的
- 注意: Vue-cli提供的代理功能,只是讓你在開發環境下使用的,它(http-server-middleware)依賴于node環境,生產代碼應該使用npm run build然后把dist放到nginx服務器上,在nginx上配置代理地址
- vue在開發中,可以通過自帶的腳手架配置實現跨域訪問,但是打包時不會將這部分配置文件載入,這樣會導致上了生產環境出現跨域訪問的問題。
4.2.2 nginx配置
vim /etc/nginx/nginx.conf
location /api/ { proxy_pass https://www.easy-mock.com/mock/5d4b7d772b863e1413ad66ab/iVP/; }
跨域問題:
這里的跨域配置是打包后,nginx做的代理轉發。與在開發模式的proxytable沒有任何關系。
如果nginx不進行跨域的配置,雖然項目部署了,但是服務根本就會訪問不到。
4.2 vue+node.js
- 項目使用 Apache http server作為啟動容器
- 把前端頁面放置在/var/www/html下
5. 上線項目(非開發環境)前端是如何解決跨域的
未讀
前端開發如何獨立解決跨域問題
*. 0.0.0.0代表什么
vue-cli生成的項目在config/index.js中有個host屬性,默認配置是0.0.0.0,這時同局域網下的其他機器可以通過本機ip訪問服務,改成localhost或者127.0.0.1后就無法訪問。
localhost、127.0.0.1、本機ip、0.0.0.0 的區別
6. 頁面中有多個圖表,如何進行布局
7. 一個寬度未知,可能是塊級或行內塊的元素,如何水平居中
8. Nginx node.js
9. echarts圖表的點擊事件
10. 權限管理
11. 如何限制對頁面的訪問,頁面跳轉要監聽路由嗎
12. 頁面中有多個圖表,如何處理,是否封裝函數來處理配置項
13. promise()里resolve()外的代碼是立即執行的嗎
14. promise.all 而非第三方的axios.all,返回是按順序的嗎
15. git的使用
16. 原型繼承
17. 路由導航守衛(問問題的方式)
對用戶的權限控制,只允許訪問A界面,不能訪問B界面,會對路由監聽嗎?