【青训营】月影老师告诉我写好JavaScript的四大技巧——妙用特性

编程入门 行业动态 更新时间:2024-10-03 14:25:16

【青训营】月影老师<a href=https://www.elefans.com/category/jswz/34/1771394.html style=告诉我写好JavaScript的四大技巧——妙用特性"/>

【青训营】月影老师告诉我写好JavaScript的四大技巧——妙用特性

文章目录

  • 起步
  • 案例1:判断4的幂
    • 菜鸟版
    • 菜鸟学废版
    • 进阶版
    • JS特性技巧版
  • 案例2:深拷贝
    • 平平无奇普通版
    • JS特性技巧版
  • 案例3:归并排序
    • 《算法(第四版)》Java直译版
    • JS特性技巧版
  • 一些小技巧
    • 转进制
    • 交换元素
  • 总结
    • 更多相关博文

如何写好JavaScript是每一个前端工程师一直以来在思考的问题,月影老师告诉我们一些写好JavaScript的原则,同时也教了一些我们如何写好JavaScript的技巧,今天来继续跟着月影老师学JavaScript吧~~

起步

我们平时在刷题或者网上找资料的时候,得到的很多答案可能都不是用JavaScript实现的,我们就直接照搬翻译成JavaScript过来了,其实JavaScript有很多自己的特性,用的好的话直接起飞~

话不多说,我们来看案例

案例1:判断4的幂

菜鸟版

这题拿到太简单了,直接循环除以4最后能除尽就是啦

① 负数直接返回 false

② 对n进行循环除以4的遍历,只要有一次不能被4整除,就返 false

③ 否则返回 true

var isPowerOfFour = function(n) {if( n < 1) return false while(n > 1){if(n % 4) return falsen /= 4}return true
};

看看LeetCode上执行的结果

还不错,够用了~

菜鸟学废版

我们使用位运算来提高效率啊

一个数x模4就相当于 x 的二进制形式 与 二进制数 11 也就是十进制的 3 按位相,(与运算是两个数都为1结果才为1,否则结果都是0)因为11前面都是0,所以x的二进制形式最后只剩最后两位,最后两位 与 11 做与运算,结果还是自身(x的二进制形式的最后两位),所以 n % 4n & 3 是一样的;

一个数除以4,相当于把他的二进制形式向右移动2位(向右移动一位相当于除以2),所以 n / 4n >>> 2 是一样的

var isPowerOfFour = function(n) {if( n < 1) return false while(n > 1){if(n & 3) return falsen >>>= 2}return true
};

看看LeetCode上执行的结果

进阶版

4的幂的前提是必须是2的幂,2的幂的前提必须是非负数

我们这里有三个判断,全部符合才是true

function isPowerOfFour(n) { return n > 0 && (n & (n - 1)) === 0 && (n & 0xAAAAAAAA) === 0; 
}

n > 0 —— > 必须是非负数

(n & (n - 1)) === 0 ——> 必须是2的幂

n & (n - 1)之前我们说过这样操作可以将 n 二进制表示的最低位 1 移除

我们再来看看2的幂数的二进制表示

1 0000 0001

2 0000 0010

4 0000 0100

8 0000 1000

16 0001 0000

32 0100 0000

64 1000 0000

所以满足 (n & (n - 1)) === 0 的数 都是 2 的幂

【注意】这里位元算外面的括号,由于位运算的优先级比较低,所以这个括号是不可省略的

(n & 0xAAAAAAAA) === 0 ——> 在2的幂的基础上必须是4的幂

0xAAAAAAAA也就是0b1010101010101010 ,它的所有偶数二进制位都是 0,所有奇数二进制位都是 1。
这样一来,我们将 n 和 0xAAAAAAAA 进行按位运算,如果结果为 0,说明 n 二进制表示中的 1 出现在偶数的位置,这样就排除了 2, 8, 32 之类的是2的幂不是4的幂的数字。

看看LeetCode上执行的结果

效率不咋地啊
不过多测几次还不一样

JS特性技巧版

都做到位运算了,为什么不更深层次的看看4的幂的数的二进制的特点呢?
1 0000 0001

4 0000 0100

16 0001 0000

64 0100 0000

4的幂的二进制都是1开头,后面偶数个零这样的形式

我们将n转换成2进制,然后 用 正则匹配结果作为返回值即可

function isPowerOfFour(n) { n = n.toString(2) return /^1(?:00)*$/.test(n) 
}

看看LeetCode上执行的结果

还可以的样子啊~

案例2:深拷贝

平平无奇普通版

function deepClone(obj){if (typeof obj !== 'object' || obj === null){return obj}let result = Array.isArray(obj) ? []: {}for (let key in obj) {if(obj.hasOwnProperty(key)) {result[key] = deepClone(obj[key])}}return result
}

JS特性技巧版

我们用JSON这个API就很简单啦

function deepClone1(target) {// 通过数据创建JSON格式的字符串let str = JSON.stringify(target);// 将 JSON 字符串创建为JS数据let data = JSON.parse(str);return data;
}

写成一行就是这样啦~

function deepClone1(target) {return JSON.parse(JSON.stringify(target));
}

案例3:归并排序

《算法(第四版)》Java直译版

在《算法(第四版)》中关于归并排序的代码从Java翻译成JavaScript就是这样

/*** 排序数组* @param {number[]} nums* @return {number[]}*/
var sortArray = function (nums) {const N = nums.length;let temp = new Array();mergeSort(nums, 0, N - 1, temp);return nums;
};/*** 归并排序  采用自顶向下的递归方法* @param {number[]} nums* @param {number} left* @param {number} right* @param {number[]} temp* @returns*/
var mergeSort = function (nums, left, right, temp) {// 如果指针重叠了就返回if (left >= right) {return;}// let mid = Math.floor(left + (right - left) / 2);let mid = (left + right) >> 1;// 递归调用mergeSortmergeSort(nums, left, mid, temp);mergeSort(nums, mid + 1, right, temp);// 归并两个有序数组merge(nums, left, mid, right, temp);
};/*** 归并两个有序数组* @param {number[]} nums* @param {number} left* @param {number} mid* @param {number} right* @param {number[]} temp*/
var merge = function (nums, left, mid, right, temp) {// 将nums复制到temp中去for (let k = left; k <= right; k++) {temp[k] = nums[k];}// 给两个数组分别定义一个指针let i = left;let j = mid + 1;// 将temp中的元素按规则写回numsfor (let k = left; k <= right; k++) {if (i > mid) {// 左半边取尽,取右半边元素nums[k] = temp[j];j++;} else if (j > right) {// 右半边取尽,取左半边元素,左指针右移nums[k] = temp[i];i++;} else if (temp[i] <= temp[j]) {// 谁小就取谁 ,左边小nums[k] = temp[i];i++;} else {// 右边小nums[k] = temp[j];j++;}}
};

其实在JavaScript数组有很多自带的方法,使得我们的数组可以直接当作队列或者栈才操作,用起来很方便

JS特性技巧版

使用JavaScript中数组的一些方法,使得归并排序实现起来异常简单,不用涉及过多的指针问题

更多内容我在之前的博文中有所介绍【算法】经典排序算法总结-JavaScript描述-图解-复杂度分析-插入-快速-归并-堆排序等

/*** 归并排序算法* @param {*} arr 数组* @returns 有序数组*/
function mergeSort(arr) {// 采用自顶向下的递归方法const N = arr.length;if (N < 2) {// 递归出口,数组只有一个元素,直接返回这个数组return arr;}// x >> 1 是位运算中的右移运算,表示右移一位,等同于 x 除以 2 再取整,即 x >> 1 === Math.floor(x / 2)// N >> 1 和 Math.floor(N / 2) 等价let middle = N >> 1;// 拆分为两个子数组let left = arr.slice(0, middle);let right = arr.slice(middle);// 递归调用mergeSortreturn merge(mergeSort(left), mergeSort(right));
}/*** 对两个有序数组进行合并操作* @param {*} left left数组* @param {*} right right数组* @returns 一个有序数组temp*/
function merge(left, right) {// 临时数组存储归并后的数据const temp = [];// 两个数组都还没有遍历结束while (left.length && right.length) {// 注意: 判断的条件是小于或等于,如果只是小于,那么排序将不稳定.if (left[0] <= right[0]) {// left[0]小,删除left数组中第一项left[0],并将它放入temp数组中temp.push(left.shift());} else {// 删除right数组中第一项,并将它放入temp数组中temp.push(right.shift());}}// left数组还有元素,right数组遍历完了while (left.length) {// 将left数组剩下的元素都放入temp数组中temp.push(left.shift());}// right数组还有元素,left数组遍历完了while (right.length) {temp.push(right.shift());}// 返回排序好的数组return temp;
}

一些小技巧

转进制

将十进制数转换成各种进制

124.toString(12)

交换元素

let a = 1, b = 2

一般情况下是这样操作的

let temp = a
a = b
b = temp

JavaScript可以直接这样交换元素的值

[a, b] = [b ,a]

JavaScript的自有特性当然远远不止这些,后面我也会继续进行归纳总结的~

总结

  1. 一些位元算可以提高代码的执行效率,可以在数字的一些运算的时候考虑他们的二进制
  2. JavaScript中有很多好用的特性,我们要会利用好
  3. 后面我会再总结关于JavaScript位运算与小技巧的博文,敬请期待

更多相关博文

【青训营】月影老师告诉我写好JavaScript的三大原则——各司其责

【青训营】月影老师告诉我写好JavaScript的三大原则——组件封装

【青训营】月影老师告诉我写好JavaScript的三大原则——过程抽象

【青训营】月影老师告诉我写好JavaScript的四大技巧——风格优先

【青训营】月影老师告诉我写好JavaScript的四大技巧——保证正确

【青训营】月影老师告诉我写好JavaScript的四大技巧——封装函数

【青训营】月影老师告诉我写好JavaScript的四大技巧——妙用特性

也可以关注专栏: 【青训营笔记专栏】

更多推荐

【青训营】月影老师告诉我写好JavaScript的四大技巧——妙用特性

本文发布于:2024-02-19 19:40:16,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1765690.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:告诉我   月影   妙用   写好   特性

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!