常用JavaScript的高階技巧

itwangchen發表於2019-04-02

前言

程式設計是一件很快樂的事,實現一個目的,我們可以有很多方法路徑,在這篇文章我們介紹一些JavaScript的奇技淫巧,僅供大家參考,各路大神在平時的程式碼編寫時,如很多簡潔高效的書寫方式;歡迎各位在下方留言。

一、資料型別檢測

1.1 typeof

typeof操作符返回一個字串,表示未經計算的運算元的型別;該運算子資料型別(返回字串,對應列表如圖)

常用JavaScript的高階技巧

1.2 instanceof

var str = "This is a simple string"; 
var num = 1111;
var boolean = true;
var und = undefined;
var nl = null;
var sb = Symbol('1111');
var obj = {}; // 非原始型別資料字面量定義

console.log(str instanceof String);         // false
console.log(num instanceof Number);         // false
console.log(boolean instanceof Boolean);    // false
console.log(nl instanceof Object);          // false
console.log(sb instanceof Symbol);          // false
console.log(obj instanceof Object);         // true

var strN = new String("This is a simple string");
var numN = new Number(1111);
var booleanN = new Boolean(true);
var objN = new Object();

console.log(strN instanceof String);            // true
console.log(numN instanceof Number);            // true
console.log(booleanN instanceof Boolean);       // true
console.log(objN instanceof Object);            // true

複製程式碼

instanceof運算子用於測試建構函式的prototype屬性是否出現在物件的原型鏈中的任何位置; 由上結果,字面量產出的原始資料型別無法使用instanceof判斷。

1.3 Object.propotype.toString

Object.prototype.toString.call('string');       //"[object String]"
Object.prototype.toString.call(1111);           //"[object Number]"
Object.prototype.toString.call(true);           //"[object Boolean]"
Object.prototype.toString.call(null);           //"[object Null]"
Object.prototype.toString.call(undefined);      //"[object Undefined]"
Object.prototype.toString.call(Symbol('111'));  //"[object Symbol]"
Object.prototype.toString.call({});             //"[object Object]"

複製程式碼

上述方法最為便捷有效

1.4 constructor

比較物件的建構函式與類的建構函式是否相等

var a = {}
a.constructor === Object     // true

var b = '111';
b.constructor === String    // true

var strN = new String('11111');
strN.constructor === String // true

var c = true;
c.constructor === Boolean   // true

var d = Symbol('symbol')
d.constructor === Symbol    // true

複製程式碼

1.5 propotype

比較物件的原型與建構函式的原型是否相等

var a = {}
a.__proto__ === Object.prototype     // true

var t = new Date();
t.__proto__ === Date.prototype      // true


var str = 'sting';
str.__proto__ === String.prototype  // true

var strN = new String('11111');
strN.__proto__ === String.prototype // true

複製程式碼複製程式碼

二、資料特殊操作

2.1 交換兩個值

2.1.1 利用一個數異或本身等於0和異或運算子合交換率

var a = 3;
var b = 4
a ^= b; // a = a ^ b
b ^= a;
a ^= b;

console.log(a, b);

複製程式碼

2.1.2 使用ES6解構賦值

let a = 1;
let b = 2;

[b, a] = [a, b];

console.log(a, b);

複製程式碼

2.2 小數取整

var num = 123.123

// 常用方法
console.log(parseInt(num)); // 123
// “雙按位非”操作符
console.log(~~ num); // 123
// 按位或
console.log(num | 0); // 123
// 按位異或
console.log(num ^ 0); // 123
// 左移操作符
console.log(num << 0); // 123

複製程式碼複製程式碼

2.3 數字金額千分位格式化

2.3.1 使用Number.prototype.toLocaleString()

var num = 123455678;
var num1 = 123455678.12345;

var formatNum = num.toLocaleString('en-US');
var formatNum1 = num1.toLocaleString('en-US');

console.log(formatNum); // 123,455,678
console.log(formatNum1); // 123,455,678.123

複製程式碼

2.3.2 使用正規表示式

var num = 123455678;
var num1 = 123455678.12345;

var formatNum = String(num).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
var formatNum1 = String(num1).replace(/\B(?=(\d{3})+(?!\d))/g, ',');

console.log(formatNum); // 123,455,678
console.log(formatNum1); // 123,455,678.12,345

複製程式碼

三、物件資料常用操作

3.1 深度克隆技巧

  • 3.1.1 JSON.stringify 轉換成字元, JSON.parse重新生成JSON資料型別
function deepClone(obj) {
    return JSON.parse(JSON.stringify(obj));
}
var obj = {
    number: 1,
    string: 'abc',
    bool: true,
    undefined: undefined,
    null: null,
    symbol: Symbol('s'),
    arr: [1, 2, 3],
    date: new Date(),
    userInfo: {
        name: 'Better',
        position: 'front-end engineer',
        skill: ['React', 'Vue', 'Angular', 'Nodejs', 'mini programs']
    },
    func: function () {
        console.log('hello better');
    }
}

console.log(deepClone(obj))

複製程式碼

從列印結果可以得出以下結論:

  1. undefined、symbol、function 型別直接被過濾掉了

  2. date 型別被自動轉成了字串型別

  • 3.1.2 常用方式 簡單遞迴
function deepClone(obj) {
    var newObj = obj instanceof Array ? [] : {};
    for (let i in obj) {
        newObj[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]
    }
    return newObj;
}

var obj = {
    number: 1,
    string: 'abc',
    bool: true,
    undefined: undefined,
    null: null,
    symbol: Symbol('s'),
    arr: [1, 2, 3],
    date: new Date(),
    userInfo: {
        name: 'Better',
        position: 'front-end engineer',
        skill: ['React', 'Vue', 'Angular', 'Nodejs', 'mini programs']
    },
    func: function () {
        console.log('hello better');
    }
}

console.log(deepClone(obj))

複製程式碼

從列印的結果來看,這種實現方式還存在很多問題:這種方式只能實現特定的object的深度複製(比如物件、陣列和函式),不能實現null以及包裝物件Number,String ,Boolean,以及Date物件,RegExp物件的複製。

3.2 物件遍歷方式

3.2.1 for-in

function A() {
	this.a = 1
	this.b = 1
}

A.prototype = {
	c: 1,
	d: 2
}

var a = new A()

for(var i in a) {
    console.log(i)
}

複製程式碼

由上列印結果可知,for-in 會遍歷物件屬性,包括原型鏈中的屬性

3.2.2 Object.entries()

function A() {
	this.a = 1
	this.b = 1
}

A.prototype = {
	c: 1,
	d: 2
}

var a = new A()
var et = Object.entries(a)
console.log(et)

複製程式碼

由上結果可知,entries 返回一個給定物件自身可列舉屬性的鍵值對陣列

3.2.3 Object.keys()、 Object.values()

function A() {
	this.a = 1
	this.b = 1
}

A.prototype = {
	c: 1,
	d: 2
}

var a = new A()
var keys = Object.keys(a)
var values = Object.values(a)
console.log(keys, values)

複製程式碼

由上結果可知,keys, values 返回一個給定物件自身可列舉屬性陣列,自身可列舉屬性值的陣列

四、陣列常用操作

4.1 陣列去重

  • 4.1.1 Set 去重
var arr = [1,2,1,1,22,4,5,6];
arr1 = [...new Set(arr)];

複製程式碼
  • 4.1.2 結合使用陣列filter方法和indexOf()方法
var arr = [1, 2, 3, 2, 6, '2', 3, 1];
function uniqueArr (arr) {
    return arr.filter(function (ele, index, array) {
        // 利用陣列indexOf()方法,返回找到的第一個值的索引
        // 如果陣列元素的索引值與indexOf方法查詢返回的值不相等,則說明該值重複了,直接過濾掉
        return array.indexOf(ele) === index;
    })
}

複製程式碼

4.2 多維陣列一行程式碼實現一維轉換

var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];

var resultArr = arr.toString().split(',').map(Number);

console.log(resultArr); // [1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]

複製程式碼

4.3 一行程式碼實現獲取一個網頁使用了多少種標籤

[...new Set([...document.querySelectorAll('*')].map(node => node.tagName))].length;
複製程式碼複製程式碼

4.4 如何實現a == 1 && a == 2 && a == 3

4.4.1 改寫陣列的toString方法

var a = [1, 2, 3];
// a.join = a.shift;
// a.valueOf = a.shift;
a.toString = a.shift;

console.log(a == 1 && a == 2 && a == 3); // true

複製程式碼

原理:當複雜型別資料與基本型別資料作比較時會發生隱性轉換,會呼叫toString()或者valueOf()方法

4.4.2 改寫物件的toString方法

var a = {
    value: 1,
    toString: function () {
        return a.value++;
    }
}
console.log(a == 1 && a == 2 && a == 3); // true

複製程式碼

4.5 統計字串中相同字元出現的次數

var str = 'aaabbbccc66aabbc6';

var strInfo = str.split('').reduce((p, c) => (p[c]++ || (p[c] = 1), p), {});

console.log(strInfo); // {6: 3, a: 5, b: 5, c: 4}

複製程式碼

4.6 將類陣列物件轉成陣列

4.6.1 使用Array.prototype.slice

var likeArrObj = {
    0: 1,
    1: 2,
    2: 3,
    length: 3
}

var arr1 = Array.prototype.slice.call(likeArrObj); // 或者使用[].slice.call(likeArrObj);
console.log(arr1); // [1, 2, 3]

複製程式碼

4.6.2 使用Array.from

var likeArrObj = {
    0: 1,
    1: 2,
    2: 3,
    length: 3
}

var arr = Array.from(likeArrObj);
console.log(arr); // [1, 2, 3]複製程式碼


相關文章