這個問題,先看一個題目,網上不少地方都有javascript
1.toString() // Uncaught SyntaxError: Invalid or unexpected token
1.1.toString() // 1.1
undefined.toString() // VM230:1 Uncaught TypeError: Cannot read property 'toString' of undefined
{}.toString() // Uncaught SyntaxError: Unexpected token
({}).toString() // [object, object]
null.toString() // VM369:1 Uncaught TypeError: Cannot read property 'toString' of null
[].toString() // ''
[1, 2].toString() // 1,2
(function () {}).toString()// function () {}
'0'.toString() // '0'
複製代碼
主要考點是:html
1.toString()
js 整數後面加的第一個點,判斷爲浮點數{}.toString()
{} 多是 js 的語句解構,如 if () {}
、function () {}
等const awaitWrap = (promise) => {
return promise
.then(res => [null, res])
.catch(err => [err, null])
}
const [res, data] = awaitWrap(sendRequest())
if (err) {
// todo
}
const data = res.body
複製代碼
參考vue
回答這個問題,首先想到js函數柯里化, 用在哪裏?除了面試題出現比較多,真正用的地方比較簡單應用,可是這樣簡單的應用可讓我省去很多代碼?java
首先舉一個例子,計算一個商品打折價格例子:node
// 獲取 1 折商品價格
const getPiceByDiscountOne = function (price) {
return price * 0.1
}
// 獲取 2 折商品價格
const getPiceByDiscountTwo = function (price) {
return price * 0.2
}
// 獲取 3 折商品價格
const getPiceByDiscountThree = function (price) {
return price * 0.3
}
// 獲取 4 折商品價格
const getPiceByDiscountFour = function (price) {
return price * 0.4
}
// ...
複製代碼
這樣太難看了,用柯里化改進一下jquery
const getDiscountFn = function (discount) {
return function (price) {
return price * discount
}
}
// 獲取 1 折商品價格
const getPiceByDiscountOne = getDiscountFn(0.1)
// 獲取 2 折商品價格
const getPiceByDiscountTwo = getDiscountFn(0.2)
// 獲取 3 折商品價格
const getPiceByDiscountThree = getDiscountFn(0.3)
// 獲取 4 折商品價格
const getPiceByDiscountFour = getDiscountFn(0.4)
// ...
複製代碼
這樣看了,是否是很易讀,你可以爲例子仍是少,還有一個場景,就是表單驗證,這應該是我想到最廣泛的場景。ios
const getValidateFn = function (rgx) {
return function (str) {
return rgx.test(str)
}
}
// 驗證是否數字
valiDateNumber = getValidateFn(/^\d$/)
// 驗證是否字母
validateAz = getValidateFn(/^\w$/)
// 驗證是不是11位數字
valiDateNumbe11r = getValidateFn(/^\d{11}$/)
// todo
複製代碼
彷佛發現一點規律。不妨我先看一下,柯里化定義: 只傳遞給函數一部分參數來調用它,讓它返回一個函數去處理剩下的參數。git
改一下規則:只傳遞給函數相同功能參數來調用它,讓它返回的函數去處理剩下的參數。這就是上述代碼簡化的原則。es6
是否是以爲哪裏有不對呀?咱們看到柯里化都是這樣的—— add(1)(2)(3)...
,說句實話,除了面試題和教程,真沒看到代碼又這麼用過。至於函數編程什麼的,那個話題太大,看下面參考。github
大佬,JavaScript 柯里化,瞭解一下?
理解JavaScript的柯里化
看到 instanceof,立馬想到兩點;
一、 typeof、instanceof、Object.prototype 的類型檢測 二、instanceof和多全局對象(多個frame或多個window之間的交互)
這兩個算基本常識,不論面試或者項目中,都不會在這個上犯傻。在 instanceof 犯傻,是這類面試題:
Object instanceof Function // true
Object instanceof Object // true
Function instanceof Object // true
Function instanceof Function // true
Array instanceof Function // true
Array instanceof Array // false
// ...
複製代碼
首先題目主要考的知識點,不是 instanceof ,是 javascript原型鏈。我在 mdn 上查到 instanceof 的定義 :instanceof運算符用於測試構造函數的prototype屬性是否出如今對象(實例)的原型鏈中的任何位。
根據定義,能夠得出這定論: instanceof 左邊是對象,右邊是構造函數(一般成爲類)。
稍加理解一下,不就很清楚知道Array instanceof Array
爲何是 false?,左邊的Array是對象(實例),這時,實例的原型鏈 Array.__proto__
=> Function.prototype
=>Function.prototype.__proto__
=>Object.prototype
,Array 構造函數的 prototype 屬性就是Array.prototype
,一看 Array.prototype
並無出現左邊 Array 的原型鏈中。
總結一下:瞭解這一點,對本身業務開發,實際沒有特別做用,徹底解答本身內心的疑問。
首先, 數組去重用 es6 最優的解以下:
Array.from(new Set(ary))
複製代碼
或
[...new Set(ary)]
複製代碼
上面只是應對面試,必須知道 es五、es6 的數組的方法去實現去重。尤爲是迭代方法、splice方法、indexOf方法,迭代方法包含filter、some、every、map、match、find、findIndex等。
splice 方法主要功能,刪除數組某個元素,固然它有不少用法。 indexOf 方法主要檢測數組存在某個元素,爲何通用它了,不用find?主要應爲性能快,能夠從兩個緯度出發,一、語言設計上,find 是一種迭代器,迭代器在遍歷查詢至少找了 n 次,indexOf 查找即返回;二、直接性能測試,比什麼都來的快一些。
迭代方法均可以用來去重,去重只不過有兩種思路:
說了這麼多,其實,我想說的這種題目很基礎,主要的意義在於理解數組增刪改查,僅此而已,若是要算算法什麼的,那都是後話。
首先說明,url 參數一般來講,尤爲在協做,建議使用 location.search。不知道對方面是的模塊使用什麼框架,並不能依靠框架的提供api,如 vue-router 的query。
傳統的實現
function getParamsObj (url) {
ulr = decodeURIComponent(url) // 考慮 decodeURIComponent
let search = url.split('?')[1] // 考慮 ?
search = search && search.split('#')[0] // 考慮hash
const obj = {}
return search.split('&')
.map(item => {
const keyValue = item.split('=')
const key = keyValue[0]
const value = keyValue[1]
obj[key] = value
})
}
複製代碼
用 UrlSearchParams 實現
function getParamsObj(url) {
url = decodeURIComponent(url) // 考慮 decodeURIComponent
let search = url.split('?')[1] // 考慮 ?
search = search && search.split('#')[0] // 考慮hash
search = new URLSearchParams(url)
const urlObj = {}
for (let [key, value] of search.entries()) {
urlObj[key] = value
}
}
複製代碼
尾調用優化:只保留內層函數的調用幀
尾調用
定義:某個函數的最後一步是調用另外一個函數 形式:function f(x) { return g(x); }
尾遞歸
定義:函數尾調用自身 做用:只要使用尾遞歸就不會發生棧溢出,相對節省內存 實現:把全部用到的內部變量改寫成函數的參數並使用參數默認值
爲何說這?最近在學算法,尾遞歸可實現比較複雜的邏輯,例如求最大公約數:
function getCd (a, b) {
if (b === 0) {
return a
} else {
return getCd(b, a % b)
}
}
複製代碼
leetcode有這麼個題目,驗證字符是否由重複子串組成?。
答案很簡單:
const hasRepeatStrCom = (str) => {
return /^(\w+)\1+$/i.test(str)
}
hasRepeatStrCom('abab') // true
hasRepeatStrCom('ababc') // false
// 隨便說一句,像不少題目考察,最後變成一個純函數,能夠寫單測
複製代碼
這種小的知識點,只要實踐一次,有了印象,最後就變成積累,因此要多實踐。
~~1.1 // 1,取整數最快的方法
^1 // 0 取反
複製代碼
ajax 的封裝分爲三個步驟
Content-Type: application/x-www-form-urlencoded
(function () {
// 參數的編碼問題
const _stringfyParams = function (data) {
var ary = [];
for (var i in data) {
var item = encodeURIComponent(i) + '=' + encodeURIComponent(data[i])
ary.push(item)
}
return ary.join('&')
}
// xhr 瀏覽器版本問題
function _createXHR() {
if (typeof XMLHttpRequest !== 'undefined') {
return new XMLHttpRequest();
} else if (typeof ActiveXObject != 'undefined') {
var versions = [
'MSXML2.XMLHttp.6.0',
'MSXML2.XMLHttp.3.0',
'MSXML2.XMLHttp'
];
for (var i = 0; i < versions.length; i++) {
try {
return newActiveXObject(version[i]);
} catch (e) {
//跳過
}
}
} else {
thrownewError('您的瀏覽器不支持 XHR對象!')
}
}
function $ajax(obj) {
// 第 1 步 建立一個 XMLHttpRequest 實例
var xhr = new _createXHR();
obj.url = obj.url + '?rand=' + Math.random()
obj.data = _stringfyParams(obj.data)
if (!('async' in obj)) obj.async = true
if (obj.method === 'get') obj.url += obj.url.indexOf('?') === -1 ? '?' + obj.data : '&' + obj.data
// 第 2 步聲明事件監聽回調
if (obj.async === true) {
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) _callback()
}
}
// 第 3 步 執行 xhr 發生請求步驟 1. open,2. 設置post的請求頭 3. send
xhr.open(obj.method, obj.url, obj.async);
if (obj.method === 'post') {
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
xhr.send(obj.data);
} else {
xhr.send(null);
}
if (obj.async === false) {
_callback();
}
// 回調函數
function _callback() {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
obj.success(xhr.responseText)
} else {
alert('數據返回失敗!狀態代碼:' + xhr.status + ',狀態信息:' + xhr.statusText)
}
}
}
window.$ajax = $ajax
})()
複製代碼
測試
document.addEventListener('click', function () {
$ajax({
method: 'get',
url: './get.json',
data: {
'name': '無樣'
},
success: function (text) {
console.log(text)
},
async: true
})
}, false)
複製代碼
總結:
如今對 ajax 的使用,基本上使用 jquery 的 $.ajax()
、axios、fetch的api。
分別運行 commonjs.js 和 es6.js:
// counter.js
exports.count = 0
setTimeout(function () {
console.log('increase count to', ++exports.count, 'in counter.js after 500ms')
}, 500)
// commonjs.js
const {count} = require('./counter')
setTimeout(function () {
console.log('read count after 1000ms in commonjs is', count)
}, 1000)
//es6.js
import {count} from './counter'
setTimeout(function () {
console.log('read count after 1000ms in es6 is', count)
}, 1000)
複製代碼
➜ test node commonjs.js
increase count to 1 in counter.js after 500ms
read count after 1000ms in commonjs is 0
➜ test babel-node es6.js
increase count to 1 in counter.js after 500ms
read count after 1000ms in es6 is 1
複製代碼
undefine、string、function、boolean、number 均能被檢測,其餘一概返回 'object'
不太靠譜,驗證是 Array 仍是 Object,還要多驗證一次
基本上可以驗證全部類型
只能驗證Array
function deepCopy(obj){
if(typeof obj === "object" && obj !== null){
var result = obj.constructor == Array ? [] : {};
for(let i in obj){
result[i] = typeof obj[i] == "object" ? deepCopy(obj[i]) : obj[i];
}
} else {
var result = obj;
}
return result;
}
複製代碼
待續。。。