四十九个javascript小知识实用技巧


Posted in Javascript onNovember 20, 2021
目录

前言:

迄今为止,我在博客上面写的关于js 和javascript的文章已经不少了,最近看了一篇国外的博客,里面总结了一些js实用技巧,本来想直接翻译一下放在我的博客上,但是网上查了一下,貌似已经有网友翻译了,在这里就不多做累赘的工作。在这个的基础上,融合我之前看到的一些js知识,一起总结在我的博客上吧。关于jquery的常用代码,我之前也总结过,大家可以去看一下。

一、js整数的操作

使用|0和~~可以将浮点转成整型且效率方面要比同类的parseInt,Math.round 要快,在处理像素及动画位移等效果的时候会很有用。性能比较见此。

var foo = (12.4 / 4.13) | 0;//结果为3
var bar = ~~(12.4 / 4.13);//结果为3

还有一个小技巧,就是!!2个叹号,可以讲一个值,快速转化为布尔值。你可以测试一下!

var eee="eee";
alert(!!eee)

返回的是true,也就是说任何一个值前面加!!都可以恒等于true。除非这个值本来就是布尔值,或者为 undefined, null, 0, false, NaN, '',因为我提到的 undefined, null, 0, false, NaN, '' ,这些,本来就是false,所以加了两个!!之后,还是fasle。

二、重写原生alert,记录弹框次数

(function() {
    var oldAlert = window.alert,
        count = 0;
    window.alert = function(a) {
        count++;
        oldAlert(a + "\n You've called alert " + count + " times now. Stop, it's evil!");
    };
})();
alert("Hello Haorooms");

三、数字交换不声明中间变量的方法

两个数字之间做交换,我们的一般做法是声明一个中间变量,但是今天的做法比较奇葩,不用声明中间变量,看看是如何实现的!

var a=1,b=2;a=[b,b=a][0];
console.log('a:'+a+',b:'+b);

 //输出a:2,b:1

怎么样,这个方法是不是有一种焕然一新的感觉?

四、万物皆对象

JavaScript的世界,万物皆对象。除了nullundefined,其他基本类型数字,字符串和布尔值都有对应有包装对象。对象的一个特征是你可以在它身上直接调用方法。

对于数字基本类型,当试图在其身上调用toString方法会失败,但用括号括起来后再调用就不会失败了,内部实现是用相应的包装对象将基本类型转为对象。所以(1).toString()相当于new Number(1).toString()。因此,你的确可以把基本类型数字,字符串,布尔等当对象使用的,只是注意语法要得体。

同时我们注意到,JavaScript中数字是不分浮点和整形的,所有数字其实均是浮点类型,只是把小数点省略了而以,比如你看到的1可以写成1.,这也就是为什么当你试图1.toString()时会报错,所以正确的写法应该是这样:1..toString(),或者如上面所述加上括号,这里括号的作用是纠正JS解析器,不要把1后面的点当成小数点。内部实现如上面所述,是将1.用包装对象转成对象再调用方法。

五、If语句的变形

当你需要写一个if语句的时候,不妨尝试另一种更简便的方法,用JavaScript中的逻辑操作符来代替。


 

比如上面的代码,首先得到今天的日期,如果是星期天,则弹窗,否则什么也不做。我们知道逻辑操作存在短路的情况,对于逻辑与表达式,只有两者都真才结果才为真,如果前面的day变量被判断为假了,那么对于整个与表达式来说结果就是假,所以就不会继续去执行后面的alert了,如果前面day为真,则还要继续执行后面的代码来确定整个表达式的真假。利用这点达到了if的效果。

对于传统的if语句,如果执行体代码超过了1 条语句,则需要加花括号,而利用逗号表达式,可以执行任意条代码而不用加花括号。

if(conditoin) alert(1),alert(2),console.log(3);

六、使用===,而不是==

==(或!=)操作符在需要的时候会自动执行类型转换。===(或!==)操作不会执行任何转换。它将比较值和类型,而且在速度上也被认为优于==。

[10] === 10    // is false
[10]  == 10    // is true
'10' == 10     // is true
'10' === 10    // is false
 []   == 0     // is true
 [] ===  0     // is false
 '' == false   // is true but true == "a" is false
 '' ===   false // is false

七、使用闭包实现私有变量

function Person(name, age) {
    this.getName = function() { return name; };
    this.setName = function(newName) { name = newName; };
    this.getAge = function() { return age; };
    this.setAge = function(newAge) { age = newAge; };

    //未在构造函数中初始化的属性
    var occupation;
    this.getOccupation = function() { return occupation; };
    this.setOccupation = function(newOcc) { occupation = 
                         newOcc; };
}

八、创建对象的构造函数

function Person(firstName, lastName){
    this.firstName =  firstName;
    this.lastName = lastName;
}

var Saad = new Person("Saad", "Mousliki");

九、小心使用typeof、instanceof和constructor

var arr = ["a", "b", "c"];
typeof arr;   // return "object"
arr  instanceof Array // true
arr.constructor();  //[]

十、创建一个自调用函数(Self-calling Funtion)

这个经常被称为自调用匿名函数(Self-Invoked Anonymous Function)或者即时调用函数表达式(IIFE-Immediately Invoked Function Expression)。这是一个在创建后立即自动执行的函数,

通常如下:

(function(){
    // some private code that will be executed automatically
})();
(function(a,b){
    var result = a+b;
    return result;
})(10,20)

十一、从数组中获取一个随机项

var items = [12, 548 , 'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' , 2145 , 119];

var  randomItem = items[Math.floor(Math.random() * items.length)];

十二、在特定范围内获取一个随机数

这个代码片段在你想要生成测试数据的时候非常有用,比如一个在最小最大值之间的一个随机薪水值。

var x = Math.floor(Math.random() * (max - min + 1)) + min;

十三、在0和设定的最大值之间生成一个数字数组

var numbersArray = [] , max = 100;

for( var i=1; numbersArray.push(i++) < max;);  // numbers = [0,1,2,3 ... 100]

十四、生成一个随机的数字字母字符串

function generateRandomAlphaNum(len) {
    var rdmstring = "";
    for( ; rdmString.length < len; rdmString  += Math.random().toString(36).substr(2));
    return  rdmString.substr(0, len);
}

//调用方法generateRandomAlphaNum(15);

十五、打乱一个数字数组

var numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411];
numbers = numbers.sort(function(){ return Math.random() - 0.5});
/* the array numbers will be equal for example to [120, 5, 228, -215, 400, 458, -85411, 122205]  */

十六、 String的trim函数

String.prototype.trim = function(){return this.replace(/^\s+|\s+$/g, "");};

十七、 附加(append)一个数组到另一个数组上

var array1 = [12 , "foo" , {name: "Joe"} , -2458];

var array2 = ["Doe" , 555 , 100];
Array.prototype.push.apply(array1, array2);
/* array1 will be equal to  [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */

十八、将arguments对象转换成一个数组

var argArray = Array.prototype.slice.call(arguments);

【译者注:arguments对象是一个类数组对象,但不是一个真正的数组】

十九、验证参数是否是数字(number)

function isNumber(n){
    return !isNaN(parseFloat(n)) && isFinite(n);
}

二十、验证参数是否是数组

function isArray(obj){
    return Object.prototype.toString.call(obj) === '[object Array]' ;
}

注意:如果toString()方法被重写了(overridden),你使用这个技巧就不能得到想要的结果了。或者你可以使用:

Array.isArray(obj); // 这是一个新的array的方法

如果你不在使用多重frames的情况下,你还可以使用 instanceof 方法。但如果你有多个上下文,你就会得到错误的结果。

var myFrame = document.createElement('iframe');
document.body.appendChild(myFrame);

var myArray = window.frames[window.frames.length-1].Array;
var arr = new myArray(a,b,10); // [a,b,10]

// instanceof will not work correctly, myArray loses his constructor
// constructor is not shared between frames
arr instanceof Array; // false

【译者注:关于如何判断数组网上有不少讨论,大家可以google一下。这篇就写的挺详细的。】

二十一、获取一个数字数组中的最大值或最小值

var  numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411];
var maxInNumbers = Math.max.apply(Math, numbers);
var minInNumbers = Math.min.apply(Math, numbers);

【译者注:这里使用了Function.prototype.apply方法传递参数的技巧】

二十二、清空一个数组

var myArray = [12 , 222 , 1000 ];
myArray.length = 0; // myArray will be equal to [].

二十三、不要使用 delete 来删除一个数组中的项。

使用 splice 而不要使用 delete 来删除数组中的某个项。使用 delete 只是用 undefined 来替换掉原有的项,并不是真正的从数组中删除。

不要使用这种方式:

var items = [12, 548 ,'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' ,2154 , 119 ];
items.length; // return 11
delete items[3]; // return true
items.length; // return 11
/* items will be equal to [12, 548, "a", undefined × 1, 5478, "foo", 8852, undefined × 1, "Doe", 2154,       119]   */

而使用:

var items = [12, 548 ,'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' ,2154 , 119 ];
items.length; // return 11
items.splice(3,1) ;
items.length; // return 10
/* items will be equal to [12, 548, "a", 5478, "foo", 8852, undefined × 1, "Doe", 2154,       119]   */

delete 方法应该被用来删除一个对象的某个属性。

二十四、使用 length 来截短一个数组

跟上面的清空数组的方式类似,我们使用 length 属性来截短一个数组。

var myArray = [12 , 222 , 1000 , 124 , 98 , 10 ];
myArray.length = 4; // myArray will be equal to [12 , 222 , 1000 , 124].

此外,如果你将一个数组的 length 设置成一个比现在大的值,那么这个数组的长度就会被改变,会增加新的 undefined 的项补上。 数组的 length 不是一个只读属性。

myArray.length = 10; // the new array length is 10
myArray[myArray.length - 1] ; // undefined

二十五、使用逻辑 AND/OR 做条件判断

同(五),if变形语句!

var foo = 10;
foo == 10 && doSomething(); // 等价于 if (foo == 10) doSomething();
foo == 5 || doSomething(); // 等价于 if (foo != 5) doSomething();

逻辑 AND 还可以被使用来为函数参数设置默认值

function doSomething(arg1){
    Arg1 = arg1 || 10; // 如果arg1没有被设置的话,Arg1将被默认设成10
}

二十六、使用 map() 方法来遍历一个数组里的项

var squares = [1,2,3,4].map(function (val) {
    return val * val;
});
// squares will be equal to [1, 4, 9, 16]

二十七、四舍五入一个数字,保留N位小数

var num =2.443242342;
num = num.toFixed(4);  // num will be equal to 2.4432

二十八、浮点数问题

0.1 + 0.2 === 0.3 // is false
9007199254740992 + 1 // is equal to 9007199254740992
9007199254740992 + 2 // is equal to 9007199254740994

为什么会这样? 0.1+0.2等于0.30000000000000004。你要知道,所有的JavaScript数字在内部都是以64位二进制表示的浮点数,符合IEEE 754标准。更多的介绍,可以阅读这篇博文。你可以使用 toFixed() 和 toPrecision() 方法解决这个问题。

二十九、使用for-in遍历一个对象内部属性的时候注意检查属性

下面的代码片段能够避免在遍历一个对象属性的时候访问原型的属性

for (var name in object) {
    if (object.hasOwnProperty(name)) {
        // do something with name
    }
}

三十、 逗号操作符

var a = 0;
var b = ( a++, 99 );
console.log(a);  // a will be equal to 1
console.log(b);  // b is equal to 99

三十一、缓存需要计算和查询(calculation or querying)的变量

对于jQuery选择器,我们最好缓存这些DOM元素。

var navright = document.querySelector('#right');
var navleft = document.querySelector('#left');
var navup = document.querySelector('#up');
var navdown = document.querySelector('#down');

三十二、在调用 isFinite()之前验证参数

isFinite(0/0) ; // false
isFinite("foo"); // false
isFinite("10"); // true
isFinite(10);   // true
isFinite(undifined);  // false
isFinite();   // false
isFinite(null);  // true  !!!

三十三、避免数组中的负数索引(negative indexes)

var numbersArray = [1,2,3,4,5];
var from = numbersArray.indexOf("foo") ;  // from is equal to -1
numbersArray.splice(from,2);    // will return [5]

确保调用 indexOf 时的参数不是负数。

三十四、基于JSON的序列化和反序列化

(serialization and deserialization)

var person = {name :'Saad', age : 26, department : {ID : 15, name : "R&D"} };
var stringFromPerson = JSON.stringify(person);
/* stringFromPerson is equal to "{"name":"Saad","age":26,"department":{"ID":15,"name":"R&D"}}"   */
var personFromString = JSON.parse(stringFromPerson);
/* personFromString is equal to person object  */

三十五、避免使用 eval() 和 Function 构造函数

使用 eval Function 构造函数是非常昂贵的操作,因为每次他们都会调用脚本引擎将源代码转换成可执行代码。

var func1 = new Function(functionCode);
var func2 = eval(functionCode);

三十六、避免使用 with()

使用 with() 会插入一个全局变量。因此,同名的变量会被覆盖值而引起不必要的麻烦。

三十七、避免使用 for-in 来遍历一个数组

避免使用这样的方式:

var sum = 0;
for (var i in arrayNumbers) {
    sum += arrayNumbers[i];
}

更好的方式是:

var sum = 0;
for (var i = 0, len = arrayNumbers.length; i < len; i++) {
    sum += arrayNumbers[i];
}

附加的好处是,i 和 len 两个变量的取值都只执行了一次,

会比下面的方式更高效:

for (var i = 0; i < arrayNumbers.length; i++)

为什么?因为arrayNumbers.length每次循环的时候都会被计算。

三十八、在调用 setTimeout() 和 setInterval() 的时候传入函数,而不是字符串。

如果你将字符串传递给 setTimeout() 或者 setInterval() ,这个字符串将被如使用 eval 一样被解析,这个是非常耗时的。

不要使用:

setInterval('doSomethingPeriodically()', 1000);
setTimeOut('doSomethingAfterFiveSeconds()', 5000)

而用:

setInterval(doSomethingPeriodically, 1000);
setTimeOut(doSomethingAfterFiveSeconds, 5000);

三十九、使用 switch/case 语句,而不是一长串的 if/else

在判断情况大于2种的时候,使用 switch/case 更高效,而且更优雅(更易于组织代码)。但在判断的情况超过10种的时候不要使用 switch/case。

四十、在判断数值范围时使用 switch/case

在下面的这种情况,使用 switch/case 判断数值范围的时候是合理的:

function getCategory(age) {
    var category = "";
    switch (true) {
        case isNaN(age):
            category = "not an age";
            break;
        case (age >= 50):
            category = "Old";
            break;
        case (age <= 20):
            category = "Baby";
            break;
        default:
            category = "Young";
            break;
    };
    return category;
}
getCategory(5);  // will return "Baby"

【译者注:一般对于数值范围的判断,用 if/else 会比较合适。 switch/case 更适合对确定数值的判断】

四十一、为创建的对象指定prototype对象

写一个函数来创建一个以指定参数作为prototype的对象是有可能:

function clone(object) {
    function OneShotConstructor(){};
    OneShotConstructor.prototype= object;
    return new OneShotConstructor();
}
clone(Array).prototype ;  // []
四十二、一个HTML转义函数
function escapeHTML(text) {
    var replacements= {"<": "<", ">": ">","&": "&", "\"": """};
    return text.replace(/[<>&"]/g, function(character) {
        return replacements[character];
    });
}

四十三、避免在循环内部使用 try-catch-finally

在运行时,每次当 catch 从句被执行的时候,被捕获的异常对象会赋值给一个变量,而在 try-catch-finally 结构中,每次都会新建这个变量。

避免这样的写法:

var object = ['foo', 'bar'], i;
for (i = 0, len = object.length; i <len; i++) {
    try {
        // do something that throws an exception
    }
    catch (e) {
        // handle exception
    }
}

而使用:

var object = ['foo', 'bar'], i;
try {
    for (i = 0, len = object.length; i <len; i++) {
        // do something that throws an exception
    }
}
catch (e) {
    // handle exception
}

四十四、为 XMLHttpRequests 设置超时。

在一个XHR请求占用很长时间后(比如由于网络问题),你可能需要中止这次请求,那么你可以对XHR调用配套使用 setTimeout()

var xhr = new XMLHttpRequest ();
xhr.onreadystatechange = function () {
    if (this.readyState == 4) {
        clearTimeout(timeout);
        // do something with response data
    }
}
var timeout = setTimeout( function () {
    xhr.abort(); // call error callback
}, 60*1000 /* timeout after a minute */ );
xhr.open('GET', url, true);  

xhr.send();

此外,一般你应该完全避免同步的Ajax请求。

四十五、处理WebSocket超时

通常,在一个WebSocket连接创建之后,如果你没有活动的话,服务器会在30秒之后断开(time out)你的连接。防火墙也会在一段时间不活动之后断开连接。

为了防止超时的问题,你可能需要间歇性地向服务器端发送空消息。要这样做的话,你可以在你的代码里添加下面的两个函数:一个用来保持连接,另一个用来取消连接的保持。通过这个技巧,你可以控制超时的问题。

使用一个 timerID:

var timerID = 0;
function keepAlive() {
    var timeout = 15000;
    if (webSocket.readyState == webSocket.OPEN) {
        webSocket.send('');
    }
    timerId = setTimeout(keepAlive, timeout);
}
function cancelKeepAlive() {
    if (timerId) {
        cancelTimeout(timerId);
    }
}

keepAlive()方法应该被添加在webSOcket连接的 onOpen() 方法的最后,而 cancelKeepAlive() 添加在 onClose() 方法的最后。

四十六、原始运算符始终比函数调用要高效。

使用VanillaJS

举例来说,不使用:

var min = Math.min(a,b);
A.push(v);

而用:

var min = a < b ? a b;
A[A.length] = v;

四十七、从整数中,随机选取一个数值

有如下公式,非常有用,可以让我们随机显示某些名人名言或者新闻事件!

=Math.floor(Math.random()*可能值的总数+第一个可能的值)
例如:要想选择一个介于2到10之间的值,我们可以这么写

var num=Math.floor(Math.random()*9+2)

请记住上面公式!~

四十八、时间格式化之后,前面个位数少零处理

处理起来有很多方法,但是如下方法比较简单,也有效一些,记录一下!

function paddingLeftZero(str){
    return ("00"+str).substr(str.length);
}

四十九、js设置cookie

getCookie: function (name) {
    var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");

    if (arr = document.cookie.match(reg))
        return unescape(arr[2]);
    else
        return null;
},
setCookie: function (name, value, Days) {
    var exp = new Date();
    exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);
    document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString();
},

四十九、js获取当天24点的时间

new Date(new Date(new Date().toLocaleDateString()).getTime()+24*60*60*1000);

同理0点时间

new Date(new Date(new Date().toLocaleDateString()).getTime());

到此这篇关于四十九个javascript小知识实用技巧的文章就介绍到这了,更多相关javascript实用技巧内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
javascript算法学习(直接插入排序)
Apr 12 Javascript
js对象内部访问this修饰的成员函数示例
Apr 27 Javascript
js操作模态窗口及父子窗口间相互传值示例
Jun 09 Javascript
jQuery中:header选择器用法实例
Dec 29 Javascript
jquery使用正则表达式验证email地址的方法
Jan 22 Javascript
AngularJs根据访问的页面动态加载Controller的解决方案
Feb 04 Javascript
浏览器复制插件zeroclipboard使用指南
Mar 26 Javascript
老生常谈 js中this的指向
Jun 30 Javascript
js事件驱动机制 浏览器兼容处理方法
Jul 23 Javascript
Vue2 轮播图slide组件实例代码
May 31 Javascript
JS/HTML5游戏常用算法之碰撞检测 地图格子算法实例详解
Dec 12 Javascript
Vue的click事件防抖和节流处理详解
Nov 13 Javascript
js不常见操作运算符总结
Nov 20 #Javascript
javascript的setTimeout()使用方法总结
Nov 20 #Javascript
JavaScript异步操作中串行和并行
Nov 20 #Javascript
vue中 this.$set的使用详解
如何用vue实现网页截图你知道吗
利用 JavaScript 构建命令行应用
Nov 17 #Javascript
Ajax实现异步加载数据
Nov 17 #Javascript
You might like
PHP判断远程url是否有效的几种方法小结
2011/10/08 PHP
PHP超级全局变量数组小结
2012/10/04 PHP
php可生成缩略图的文件上传类实例
2014/12/17 PHP
PHP 绘制网站登录首页图片验证码
2016/04/12 PHP
微信支付开发订单查询实例
2016/07/12 PHP
用PHP的socket实现客户端到服务端的通信实例详解
2017/02/04 PHP
PHP实现创建微信自定义菜单的方法示例
2017/07/14 PHP
jquery 图片Silhouette Fadeins渐显效果
2010/02/07 Javascript
javaScript(JS)替换节点实现思路介绍
2013/04/17 Javascript
Jquery 的outerHeight方法使用介绍
2013/09/11 Javascript
JS 实现点击a标签的时候让其背景更换
2013/10/15 Javascript
jquery实现非叠加式的搜索框提示效果
2014/01/07 Javascript
JSON.parse()和JSON.stringify()使用介绍
2014/06/20 Javascript
微信小程序实现录制、试听、上传音频功能(带波形图)
2020/02/27 Javascript
举例讲解Python面相对象编程中对象的属性与类的方法
2016/01/19 Python
python+matplotlib实现礼盒柱状图实例代码
2018/01/16 Python
Python3多线程操作简单示例
2018/05/22 Python
python 实现selenium断言和验证的方法
2019/02/13 Python
12个步骤教你理解Python装饰器
2019/07/01 Python
使用python telnetlib批量备份交换机配置的方法
2019/07/25 Python
pandas DataFrame的修改方法(值、列、索引)
2019/08/02 Python
Python object类中的特殊方法代码讲解
2020/03/06 Python
python中setuptools的作用是什么
2020/06/19 Python
python中关于数据类型的学习笔记
2020/07/19 Python
德国大型的家具商店:Pharao24.de
2016/10/02 全球购物
马来西亚最大的在线隐形眼镜商店:MrLens
2019/03/27 全球购物
北京泡泡网网络有限公司.net面试题
2012/07/17 面试题
外科实习自我鉴定
2013/10/06 职场文书
优秀应届生推荐信
2013/11/09 职场文书
开业庆典策划方案
2014/02/18 职场文书
三严三实心得体会范文
2014/10/13 职场文书
爱国主义主题班会
2015/08/14 职场文书
2016年重阳节慰问信
2015/12/01 职场文书
使用vue判断当前环境是安卓还是IOS
2022/04/12 Vue.js
Windows Server 2008 修改远程登录端口以及配置防火墙
2022/04/28 Servers
Mysql 一主多从的部署
2022/05/20 MySQL