一、基礎知識
1. 數據類型
js 中的數據類型包含兩部分:
1)基本數據類型(String、Number、Boolean、Null、Undefined、Symbol)
2)複雜數據類型(Object)
2. typeof 的作用
用於判斷是否是某個數據類型:
var
a = 'a',
b = 1,
c = [1, 2, 3],
d = {a: 'a'},
e = new Date(),
f = new RegExp(),
g = true,
h = new Function(),
i = null,
j = undefined;
console.log(typeof a, typeof b, typeof c, typeof d, typeof e, typeof f, typeof g, typeof h, typeof i, typeof j)
// 輸出
// string number object object object object boolean function object undefined
3. 引用類型
引用類型包括:Object、Array、RegExp、Date、Function、特殊的基本包裝類型(String、Number、Boolean)以及單體內置對象(Global、Math)。
4. instanceof 的作用
用於判斷是否是某個對象類型
var a = [1,2,3];
console.log(a instanceof Object); //true
console.log(a instanceof Array); //true
console.log(a instanceof RegExp); //false
5. 類型轉換
js中有兩種強制類型轉換:
1)顯示類型轉換
-
轉換爲數值類型:Number(mix)、parseInt(string,radix)、parseFloat(string)
-
轉換爲字符串類型:toString(radix)、String(mix)
-
轉換爲布爾類型:Boolean(mix)
2)隱式類型轉換
-
用於檢測是否爲非數值的函數:isNaN(mix);
-
遞增遞減操作符(包括前置和後置)、一元正負符號操作符
-
加法運算操作符
-
乘除、減號運算符、取模運算符
-
邏輯操作符(!、&&、||)
-
關係操作符(<, >, <=, >=)
-
相等操作符(==)
6. 原型鏈
推薦文章:https://www.jianshu.com/p/dee9f8b14771
7. 閉包
閉包是指有權訪問另一個函數作用域中的變量的函數。
可以看下我寫的另一篇關於閉包的文章:閉包的理解
8. 類和繼承
五條規則:
-
所有的引用類型(數組、函數、對象)都具有對象特性,即可自由擴展屬性
-
所有的引用類型(數組、對象、函數)有一個
__proto__
屬性,屬性值是一個普通的對象 -
所有的函數都有一個
prototype
屬性,屬性值也是一個普通的對象 -
所有的引用類型(數組、對象、函數),
__proto__
屬性指向它的構造函數的prototype
屬性 -
當試圖得到一個對象的某個屬性時,如果這個對象本身沒有這個屬性,那麼回去他的
__proto__
(即它的構造函數的prototype
中尋找)
詳情傳送門:https://www.cnblogs.com/chengzp/p/extends.html
9. 變量提升與函數提升
這個很好理解,就是在某個 作用域 內,用 var 聲明的變量以及函數聲明會提升到作用域頂部。
console.log(a) // undefined
var a = 'haha';
console.log(a) // haha
由於變量提升,實際上是這樣執行的:
var a;
console.log(a)
a = 'haha';
console.log(a)
函數也是一樣,但要注意一點:只有函數聲明纔會提升整個函數代碼塊,函數表達式則只會提升標識符。
console.log(f1); // [Function: f1]
console.log(f2); // undefined
//函數聲明
function f1() {
}
//函數表達式
var f2 = function () {
}
10. this 指向問題
可參考我的一篇文章:關於this的指向問題
11. new 操作符到底幹了什麼
就幹了這些:
- 創建了一個新對象
- 將構造函數的作用域賦給新對象(因此 this 就指向了這個新對象)
- 執行構造函數中的代碼(爲這個新對象添加屬性)
- 返回新對象
用代碼表示就是:
var obj = {};
obj.__proto__ = Person.prototype;
Person.call(obj);
- 第一行,我們創建了一個空對象obj
- 第二行,我們將這個空對象的__proto__成員指向了Person函數對象prototype成員對象
- 第三行,我們將Person函數對象的this指針替換成obj,然後再調用Person函數,於是我們就給obj對象賦值了一個id成員變量,這個成員變量的值是”Person”
二、算法知識
1. 數組去重
function arrayUnique(arr) {
let a = [];
let len = arr.length;
for (let i = 0; i < len; i++) {
if (a.indexOf(arr[i]) < 0) {
a.push(arr[i])
}
}
return a
}
let newArr = arrayUnique([1, 2, 3, 2, 3, 1, 23, 4]);
console.log(newArr) //[ 1, 2, 3, 23, 4 ]
function arrayUnique(arr) {
let json = {}
let newArr = []
let len = arr.length
for (let i = 0; i < len; i++) {
if (!json[arr[i]]) {
json[arr[i]] = true
newArr.push(arr[i])
}
}
return newArr
}
let newArr = arrayUnique([1, 2, 3, 2, 3, 1, 23, 4]);
console.log(newArr) //[ 1, 2, 3, 23, 4 ]
function arrayUnique(arr) {
return Array.from(new Set(arr));
}
let newArr = arrayUnique([1, 2, 3, 2, 3, 1, 23, 4]);
console.log(newArr) //[ 1, 2, 3, 23, 4 ]
function arrayUnique(arr) {
return [...new Set(arr)];
}
let newArr = arrayUnique([1, 2, 3, 2, 3, 1, 23, 4]);
console.log(newArr) //[ 1, 2, 3, 23, 4 ]
2. 數組降維
var arr = [1, [2, [3, [4, [5, [6, [7]]]]]]]
function dimensionalityReduction(arr){
var tempArr = Array.from(arr.join('-'));
for(var i = 0;i<tempArr.length;i++){
if(isNaN(tempArr[i])){
tempArr.splice(i,1)
}
}
return tempArr; // 1,2,3,4,5,6,7
}
let flatten = arr => arr.reduce((pre,cur)=>{
Array.isArray(cur)?pre.push(...flatten(cur)):pre.push(cur);
return pre //1,2,3,4,5,6,7
},[])
3. 輸出字符中最長的沒有重複字符的字串
var str = 'aadacd'
function getMaxUniquePart(str) {
let res = 0;
let unqiueStr = '';
let maxStr = '';
let len = str.length;
for (let i = 0; i < len; i++) {
let a = str.charAt(i);
let index = unqiueStr.indexOf(a)
if (index === -1) {
unqiueStr += a
if (res <= unqiueStr.length) {
res = unqiueStr.length
maxStr = unqiueStr
}
} else {
unqiueStr = unqiueStr.substr(index + 1) + a
}
}
return maxStr
}
console.log(getMaxUniquePart(str)) //dac
這種方法有一個不足,如果有多個長度相同的子串則無法得到多個字串,只會輸出第一個。
var str = 'aadacd'
function getMax(data) {
data = data.trim();
let obj = {
start: 0
};
let nowStr = '';
let maxStr = '';
let strGroup = []
let maxLen = 0;
let len = data.length;
for (let i = 0; i < len; i++) {
let char = data[i];
if (!(obj[char] >= 0)) { // 若不重複
obj[char] = i;
nowStr += char;
} else { // 若重複
if (obj.start <= obj[char]) { // 若start指針在重複字符(重複字符的第一個字符)之前
obj.start = obj[char] + 1; // 改變start指針位置
obj[char] = i; // 改變這個字符的位置
if (nowStr.length > maxLen) { // 比較當前子串跟最長子串的長度
maxStr = nowStr; // 若大於,則替換
maxLen = nowStr.length;
nowStr = data.substring(obj.start, i + 1);
} else if (nowStr.length === maxLen) { // 若等於,則隔一個空格加在末尾
maxStr += ' ' + nowStr;
nowStr = data.substring(obj.start, i + 1);
} else { // 若小於,僅更新nowStr
nowStr = data.substring(obj.start, i + 1);
}
} else { // 若start指針在重複字符(重複字符的第一個字符)之後
obj[char] = i; // 改變這個字符的位置
nowStr = data.substring(obj.start, i + 1);
}
}
}
if (nowStr.length > maxLen) {
maxStr = nowStr;
maxLen = nowStr.length;
} else if (nowStr.length === maxLen) {
maxStr += ' ' + nowStr;
}
return maxStr
}
console.log(getMax(str)) //dac acd
不知是否還有更爲簡單的方式,望知悉。
4. 輸入一個數組和一個數,找出數組中兩個值之和爲該數,返回該倆個值的位置
function getOrder(arr, sum) {
let a = {}
let b = []
for (let i = 0; i < arr.length; i++) {
let c = sum - arr[i]
if (a[c] === undefined) {
a[arr[i]] = i
} else {
b.push([a[c], i])
}
}
return b
}
console.log(getOrder([1, 17, 8, 20, 5, 9, 0], 25)) //[ [ 1, 2 ], [ 3, 4 ] ]