前端防错以及好用小tips指南总结

2023-02-28,,

@前端防錯以及好用tips指南總結

1.一般情況下我們接收到的都是對象格式,某些情況下,需要接到後端傳過來的奇怪的字符串格式的JSON,需要解析成對象,但是有時候他們傳過來的格式有問題,會報錯

解決方案:可以将方法放在try{JSON.parse(...)}catch(e){}代码块中。
好用的JSON.stringify 方法

    // 1.1接受一个数组参数,指定需要转成字符串的属性,第二个参数指定,只转a属性。
JSON.stringify({ a: 1, b: 2 }, ['a'])
// '{"a":1}' // 1.2接受函数参数,转化对象的键和值
function f12(key, value) {
if (typeof value === "number") {
value = 2 * value;
}
return value;
} JSON.stringify({ a: 1, b: 2 }, f12)
// '{"a":2,"b":4}' // 1.3只拿自己想要的值,如果处理函数返回undefined或没有返回值,這個属性就沒了啊哈哈。
function f13(key, value) {
if (typeof (value) == "string") {
return undefined;
}
return value;
} JSON.stringify({ a: "abc", b: 123 }, f13)
// '{"b":123}' // 1.4給數據添加可讀性
var d = { a: 1, b: 2 }
JSON.stringify(d, null, 2);
// "{
// "a": 1,
// "b": 2
// }" // 1.5只输出你你想要的keys,加強版
var e = { a: 1, b: 2, c: 3, d: 4 }
JSON.stringify(e, ["a", "d"], 4);
// "{
// "a": 1,
// "d": 4
// }" // 1.5還可以這樣玩一下
JSON.stringify({ a: 1, b: 2, c: 3 }, null, '|----');
// "{
// |----"a": 1,
// |----"b": 2,
// |----"c": 3
// }" // 1.6關於JSON.parse你也可以試試看喲

2.switch case 一定要記得寫break

3.对象最後一個屬性结尾多逗号兼容IE會出問題,記得格式化一下代碼

4.輸入框防呆要注意:如果是字符串類型就用myInput && myInput.trim()

    const myInput = '   '
if (myInput && myInput.trim()) { console.log('這個輸入框不為空') }

5.禁止給未声明的变量赋值,否則會搞出来很多全局变量

6.多JS文件打包,如果你不喜歡寫分號,有時候會出問題,可以在文件開頭加個分號

7.如果你不喜歡寫分號,有時候會引起函数返回值不正确或者是代碼執行有問題

舉例說明


function e() {
return
{
a: "e"
}
}
console.log(e()) // undefined
let z = 'z'
let m = 'm'
[z, m] = [m, z]
console.log(z, m) // Uncaught ReferenceError: m is not defined let z1 = 'z';
let m1 = 'm';
[z1, m1] = [m1, z1];
console.log(z1, m1); // m z

8.Array forEach()中无法return和break,代替方法有some()与every()

    var arr = [1, 2, 3, 4, 5];
var num = 3;
arr.forEach(function (v) {
if (v == num) {
break;
}
console.log(v);
});
// Uncaught SyntaxError: Illegal break statement
var arr = [1, 2, 3, 4, 5];
var num = 3;
arr.forEach(function (v) {
if (v == num) {
return;
}
console.log(v);
});
// VM62:7 1
// VM62:7 2
// VM62:7 4
// VM62:7 5 // 解決如下,使用数组的另外两个方法some()与every():
var arr = [1, 2, 3, 4, 5];
var num = 3;
arr.some(function (v) {
if (v == num) {
return true;
}
console.log(v);
});
// VM65:7 1
// VM65:7 2
// true 跳出循環啦~~~~
var arr = [1, 2, 3, 4, 5];
var num = 3;
arr.every(function (v) {
if (v == num) {
return false;
} else {
console.log(v);
return true;
}
});
// 1
// 2
// false 跳出循環啦~~~~

小金理解的小總結
8.1 forEach没有返回值,只针对每个元素调用函數.
8.2 some 当内部return true时跳出整个循环.
8.3 every 当内部return false时跳出整个循环.
8.4 map 有返回值,返回一个新的数组,每个元素为调用函數的结果

9.需要使用到 eval()的时候,使用 Function()来搞一下

9.1 eval() 是一个危险的函数, 它使用与调用者相同的权限执行代码。如果你用 eval() 运行的字符串代码被恶意方(不怀好意的人)修改,您最终可能会在您的网页/扩展程序的权限下,在用户计算机上运行恶意代码。更重要的是,第三方代码可以看到某一个 eval() 被调用时的作用域,这也有可能导致一些不同方式的攻击。相似的 Function 就不容易被攻击。
9.2 但是,(谢天谢地)存在一个非常好的eval替代方法:只需使用 window.Function。 这有个例子方便你了解如何将eval()的使用转变为Function()。

使用eval的糟糕代码:

   function looseJsonParse(obj){
return eval("(" + obj + ")");
}
console.log(looseJsonParse(
"{a:(4-1), b:function(){}, c:new Date()}"
))

不用eval的更好的代码:

   function looseJsonParse(obj){
return Function('"use strict";return (' + obj + ')')();
}
console.log(looseJsonParse(
"{a:(4-1), b:function(){}, c:new Date()}"
))

10.箭头函数不仅没有this,常用的arguments也没有。如果你能获取到arguments,那它一定是来自父作用域的。

11.防止後端瞎搞,常用的寫法

    var ccc = { a: { t: 123 } }
function setC() { ccc['b'] = 111 }
ccc && ccc.a && ccc.a.t && setC()

12.關於arguments,你要注意一下,想要把它當成數組用的話,需要轉化一下哦~

    function setArg() {
console.log(arguments) // Arguments(4)
console.log([].slice.call(arguments)) // Array(4) ----[1,2,3,'4']
}
setArg(1, 2, 3, '4')

13.判断数组用這個:Array.isArray,別用其他的~

14.使用Object.prototype 和 for in 搭配使用可能引發的坑,要注意下下~~

14.1如果你非要用,那就記得搭配上Object.hasOwnProperty(key)

    var q = { a: 1, s: 2, d: 3 };

    Object.prototype.w = function () { };
for (var key in q) {
if (q.hasOwnProperty(key)) {
console.log('for in搭配hasOwnProperty方法', '對象的key:', key, '對象的value:', q[key]);
}
console.log('for in方法', '對象的key:', key, '對象的value:', q[key]);
}
Object.keys(q).forEach(key => {
console.log('forEach方法', '對象的key:', key, '對象的value:', q[key]);
})
Object.keys(q).some(key => {
if (key === 'e') {
return true; // some true时跳出 循环.
}
console.log('some方法', '對象的key:', key, '對象的value:', q[key]);
})
Object.keys(q).every(key => {
if (key === 'e') {
return false; // every false 跳出 循环
} else {
console.log('every方法', '對象的key:', key, '對象的value:', q[key]);
return true; }
})
// for in搭配hasOwnProperty方法 對象的key: a 對象的value: 1
// for in方法 對象的key: a 對象的value: 1
// for in搭配hasOwnProperty方法 對象的key: s 對象的value: 2
// for in方法 對象的key: s 對象的value: 2
// for in搭配hasOwnProperty方法 對象的key: d 對象的value: 3
// for in方法 對象的key: d 對象的value: 3
// for in方法 對象的key: w 對象的value: ƒ () { }
// forEach方法 對象的key: a 對象的value: 1
// forEach方法 對象的key: s 對象的value: 2
// forEach方法 對象的key: d 對象的value: 3
// some方法 對象的key: a 對象的value: 1
// some方法 對象的key: s 對象的value: 2
// some方法 對象的key: d 對象的value: 3
// every方法 對象的key: a 對象的value: 1
// every方法 對象的key: s 對象的value: 2
// every方法 對象的key: d 對象的value: 3

15.带有ID的DOM树元素會成为全局变量,SO:尽量避免使用全局变量

<div id="myDiv"></div>
<script>
if (typeof myDiv === 'undefined') {
myDiv = '測試一下我是不是字符串' // 其实这里不会执行到的
}
console.log(myDiv)
// <div id="myDiv"></div>--输出DOM对象
myDiv = '改一改變量感受一下'
console.log(myDiv)
// 改一改變量感受一下
</script>

16.關於按给定的参数创建一日期对象以及獲取瀏覽器版本

  const data1 = new Date("2019-01-01")
// Tue Jan 01 2019 08:00:00 GMT+0800 (台北标准时间)
// ie某些版本會告訴你語法錯誤
const data2 = new Date(2019,0,1)
// Tue Jan 01 2019 00:00:00 GMT+0800 (台北标准时间), IE在用版本還OK
const data3 = new Date("2019/01/01")
// Tue Jan 01 2019 00:00:00 GMT+0800 (台北标准时间), IE在用版本還OK
const userAgent1 = navigator.userAgent.toLowerCase()
// "mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/71.0.3578.98 safari/537.36"
function getBroswer(){
var Sys = {};
var ua = navigator.userAgent.toLowerCase();
var s;
(s = ua.match(/edge\/([\d.]+)/)) ? Sys.edge = s[1] :
(s = ua.match(/rv:([\d.]+)\) like gecko/)) ? Sys.ie = s[1] :
(s = ua.match(/msie ([\d.]+)/)) ? Sys.ie = s[1] :
(s = ua.match(/firefox\/([\d.]+)/)) ? Sys.firefox = s[1] :
(s = ua.match(/chrome\/([\d.]+)/)) ? Sys.chrome = s[1] :
(s = ua.match(/opera.([\d.]+)/)) ? Sys.opera = s[1] :
(s = ua.match(/version\/([\d.]+).*safari/)) ? Sys.safari = s[1] : 0; if (Sys.edge) return { broswer : "Edge", version : Sys.edge };
if (Sys.ie) return { broswer : "IE", version : Sys.ie };
if (Sys.firefox) return { broswer : "Firefox", version : Sys.firefox };
if (Sys.chrome) return { broswer : "Chrome", version : Sys.chrome };
if (Sys.opera) return { broswer : "Opera", version : Sys.opera };
if (Sys.safari) return { broswer : "Safari", version : Sys.safari }; return { broswer : "", version : "0" };
}
var abc = getBroswer();
console.log("broswer:"+abc.broswer+" version:"+abc.version);
// broswer:Chrome version:71.0.3578.98

17. js裡常用的replace方法--string/正则我們容易忽略或者忘記的地方

 var str11 = '小金:需要替換的地方:1.待替換1,2.待替換2,3.待替換3,4.待替換4,5.待替換5,6.待替換6,7.待替換7,'
var newStr11 = str11.replace('待替換', '替換過啦')
console.log(newStr11)
// 小金:需要替換的地方:1.替換過啦1,2.待替換2,3.待替換3,4.待替換4,5.待替換5,6.待替換6,7.待替換7, // 從以上我們可以看出,只替換了第一個哦~~ let myReg = new RegExp('^' + escape('待替換'))
// .replace(/%/g, '\\')
console.log(myReg) var newStr12 = str11.replace(new RegExp('待替換', 'g'), '替換過啦')
console.log("new RegExp('待替換', 'g')", newStr12)
// new RegExp('待替換', 'g') 小金:需要替換的地方:1.替換過啦1,2.替換過啦2,3.替換過啦3,4.替換過啦4,5.替換過啦5,6.替換過啦6,7.替換過啦7,
var res1 = str11.split('待替換').join('替換過啦')
console.log('split-join', res1)
// split-join 小金:需要替換的地方:1.替換過啦1,2.替換過啦2,3.替換過啦3,4.替換過啦4,5.替換過啦5,6.替換過啦6,7.替換過啦7,

结语

欢迎大家指出文章需要改正之处~

如果有更好的方法,欢迎大家提出来,共同进步哟~~

前端防错以及好用小tips指南总结的相关教程结束。