跳到主要内容

JavaScript 实用技巧

类数组转换为数组

在 JavaScript 中,类数组对象如 arguments 并不具备数组的方法。以下函数展示了如何将类数组对象转换为真正的数组。

function convertArgumentsToArray() {
const argsArray = Array.prototype.slice.call(arguments);
console.log(argsArray);
}
convertArgumentsToArray(1, 2, 3, 4, 5);

按元素字节数排序数组

有时需要根据字符串中字符的字节数对数组进行排序。Unicode 字符集中的字符有不同的字节长度,0-255 的字符为单字节,256 及以上为双字节。

const array = ['EDG牛逼', 'OK', 'NB', '必胜', '777777'];

array.sort((a, b) => getByteLength(a) - getByteLength(b));

function getByteLength(str) {
let bytes = str.length;
for (let i = 0; i < str.length; i++) {
if (str.charCodeAt(i) > 255) {
// 中文字符或特殊字符占用两个字节
bytes++;
}
}
return bytes;
}

console.log(array);

封装 typeof 方法

JavaScript 的 typeof 操作符在判断复杂数据类型时有其局限性。以下函数通过 Object.prototype.toString 方法更准确地判断数据类型。

function getType(value) {
const typeMap = {
'[object Array]': 'array',
'[object Object]': 'object',
'[object Number]': 'number',
'[object String]': 'string',
'[object Boolean]': 'boolean',
'[object Function]': 'function',
'[object Date]': 'date',
'[object RegExp]': 'regexp',
'[object Error]': 'error',
'[object Null]': 'null',
'[object Undefined]': 'undefined',
};

if (value === null) {
return 'null';
}

const type = typeof value;
if (type !== 'object') {
return type;
}

const toString = Object.prototype.toString.call(value);
return typeMap[toString] || 'object';
}

console.log(getType(1)); // number
console.log(getType('1')); // string
console.log(getType([])); // array
console.log(getType({})); // object
console.log(getType(new Boolean(true))); // boolean
console.log(getType(null)); // null
console.log(getType(undefined)); // undefined

Object.prototype.toString.call(value); 可以用于判断引用类型的具体类型。

数组去重

利用对象属性的不重复性(相同的属性名只保留一个)来实现数组去重。

const array = [0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 'a', 'a', 'a', 'a'];

Array.prototype.unique = function () {
const seen = {};
const result = [];

for (let i = 0; i < this.length; i++) {
if (!seen.hasOwnProperty(this[i])) {
seen[this[i]] = true;
result.push(this[i]);
}
}
return result;
};

console.log(array.unique());

字符串去重

通过对象属性的不重复性实现字符串中的字符去重。

const str = '1231654561adasd';

String.prototype.unique = function () {
const seen = {};
let uniqueStr = '';

for (let i = 0; i < this.length; i++) {
const char = this[i];
if (!seen.hasOwnProperty(char)) {
seen[char] = true;
uniqueStr += char;
}
}
return uniqueStr;
};

console.log(str.unique());

找出第一个不重复的字母

以下函数用于找出字符串中第一个出现一次的字母。

const str = 'sjahdspodiqnqwubgiuosdupoiqiwoepwqn';

function findFirstUniqueChar(str) {
const charCount = {};

for (let i = 0; i < str.length; i++) {
const char = str[i];
charCount[char] = (charCount[char] || 0) + 1;
}

for (let i = 0; i < str.length; i++) {
if (charCount[str[i]] === 1) {
return str[i];
}
}

return null;
}

console.log(findFirstUniqueChar(str));

练习题

重写 unshift

通过 splice 方法重写数组的 unshift 方法,用于在数组开头添加元素。

const array = ['d', 'e', 'f'];

Array.prototype.myUnshift = function () {
let position = 0;
for (let i = 0; i < arguments.length; i++) {
this.splice(position, 0, arguments[i]);
position++;
}
return this.length;
};

array.myUnshift('a', 'b', 'c');
console.log(array);

重写 unshift(方法二)

利用数组的 concat 方法实现 unshift 的功能。

const array = ['d', 'e', 'f'];

Array.prototype.myUnshift = function () {
const argsArray = Array.prototype.slice.call(arguments);
const newArray = argsArray.concat(this);
// 可选:修改原数组
this.length = 0;
for (let i = 0; i < newArray.length; i++) {
this.push(newArray[i]);
}
return this.length;
};

array.myUnshift('a', 'b', 'c');
console.log(array);

闭包

展示闭包的使用,保持私有变量的状态。

function Counter() {
let count = 0;

this.increment = function () {
count++;
console.log(count);
};
}

const counter1 = new Counter();
counter1.increment(); // 1
counter1.increment(); // 2

const counter2 = new Counter();
counter2.increment(); // 1

等同于

function Counter() {
let count = 0;

const counter = {
increment: function () {
count++;
console.log(count);
},
};
return counter;
}

const counter1 = Counter();
counter1.increment(); // 1
counter1.increment(); // 2

const counter2 = Counter();
counter2.increment(); // 1

typeofarguments

function test() {
console.log(typeof arguments);
// arguments 是类数组对象,typeof 返回 'object'
}
test();

函数字面量

展示函数表达式和函数名的作用域。

const test = function a() {
return 'a';
};

// 函数表达式中的函数名在外部不可访问
console.log(typeof a); // undefined
console.log(a); // 报错 ReferenceError: a is not defined

优化 switch 语句

通过数组替代 switch 语句来简化代码。

function printWeekday(day) {
const weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
const weekday = weekdays[day - 1];
if (weekday) {
console.log(weekday);
} else {
console.log("I don't know");
}
}

printWeekday(3); // Wed