一、js整数的操作

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

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

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

  1. var eee="eee";
  2. alert(!!eee)

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

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

  1. (function() {
  2. var oldAlert = window.alert,
  3. count = 0;
  4. window.alert = function(a) {
  5. count++;
  6. oldAlert(a + "\n You've called alert " + count + " times now. Stop, it's evil!");
  7. };
  8. })();
  9. alert("Hello Haorooms");

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

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

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

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

四、万物皆对象

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

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

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

五、If语句的变形

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

  1. var day=(new Date).getDay()===0;
  2. //传统if语句
  3. if (day) {
  4. alert('Today is Sunday!');
  5. };
  6. //运用逻辑与代替if
  7. day&&alert('Today is Sunday!');

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

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

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

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

我之前的一篇文章中写个 ==的隐性转换,请看:http://www.haorooms.com/post/js_yinxingleixing

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

  1. [10] === 10 // is false
  2. [10] == 10 // is true
  3. '10' == 10 // is true
  4. '10' === 10 // is false
  5. [] == 0 // is true
  6. [] === 0 // is false
  7. '' == false // is true but true == "a" is false
  8. '' === false // is false

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

关于闭包,我之前也有个介绍:http://www.haorooms.com/post/js_bb

  1. function Person(name, age) {
  2. this.getName = function() { return name; };
  3. this.setName = function(newName) { name = newName; };
  4. this.getAge = function() { return age; };
  5. this.setAge = function(newAge) { age = newAge; };
  6.  
  7. //未在构造函数中初始化的属性
  8. var occupation;
  9. this.getOccupation = function() { return occupation; };
  10. this.setOccupation = function(newOcc) { occupation =
  11. newOcc; };
  12. }

八、创建对象的构造函数

  1. function Person(firstName, lastName){
  2. this.firstName = firstName;
  3. this.lastName = lastName;
  4. }
  5.  
  6. var Saad = new Person("Saad", "Mousliki");

九、小心使用typeof、instanceof和constructor

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

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

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

  1. (function(){
  2. // some private code that will be executed automatically
  3. })();
  4. (function(a,b){
  5. var result = a+b;
  6. return result;
  7. })(10,20)

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

  1. var items = [12, 548 , 'a' , 2 , 5478 , 'foo' , 8852, , 'Doe' , 2145 , 119];
  2. var randomItem = items[Math.floor(Math.random() * items.length)];

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

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

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

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

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

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

  1. function generateRandomAlphaNum(len) {
  2. var rdmstring = "";
  3. for( ; rdmString.length < len; rdmString += Math.random().toString(36).substr(2));
  4. return rdmString.substr(0, len);
  5. }
  6. //调用方法generateRandomAlphaNum(15);

十五、打乱一个数字数组

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

十六、 String的trim函数

我之前写个一个去掉空格的函数,请看:http://www.haorooms.com/post/js_kong_ge

这里的是这个

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

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

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

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

  1. var argArray = Array.prototype.slice.call(arguments);
  2. 【译者注:arguments对象是一个类数组对象,但不是一个真正的数组】

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

  1. function isNumber(n){
  2. return !isNaN(parseFloat(n)) && isFinite(n);
  3. }

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

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

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

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

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

  1. var myFrame = document.createElement('iframe');
  2. document.body.appendChild(myFrame);
  3. var myArray = window.frames[window.frames.length-1].Array;
  4. var arr = new myArray(a,b,10); // [a,b,10]
  5. // instanceof will not work correctly, myArray loses his constructor
  6. // constructor is not shared between frames
  7. arr instanceof Array; // false

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

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

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

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

二十二、清空一个数组

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

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

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

不要使用这种方式:

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

而使用:

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

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

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

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

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

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

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

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

同(五),if变形语句!

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

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

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

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

关于map(),我之前的一篇文章中也写过,具体请看:http://www.haorooms.com/post/jquery_grep_join

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

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

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

二十八、浮点数问题

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

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

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

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

  1. for (var name in object) {
  2. if (object.hasOwnProperty(name)) {
  3. // do something with name
  4. }
  5. }

三十、 逗号操作符

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

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

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

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

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

  1. isFinite(0/0) ; // false
  2. isFinite("foo"); // false
  3. isFinite("10"); // true
  4. isFinite(10); // true
  5. isFinite(undifined); // false
  6. isFinite(); // false
  7. isFinite(null); // true !!!

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

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

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

三十四、基于JSON的序列化和反序列化(serialization and deserialization)

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

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

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

  1. var func1 = new Function(functionCode);
  2. var func2 = eval(functionCode);

三十六、避免使用 with()

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

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

避免使用这样的方式:

  1. var sum = 0;
  2. for (var i in arrayNumbers) {
  3. sum += arrayNumbers[i];
  4. }

更好的方式是:

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

附加的好处是,i 和 len 两个变量的取值都只执行了一次,会比下面的方式更高效:

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

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

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

关于setTimeout,我之前也写过:http://www.haorooms.com/post/js_setTimeout

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

不要使用:

  1. setInterval('doSomethingPeriodically()', 1000);
  2. setTimeOut('doSomethingAfterFiveSeconds()', 5000)

而用:

  1. setInterval(doSomethingPeriodically, 1000);
  2. setTimeOut(doSomethingAfterFiveSeconds, 5000);

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

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

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

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

  1. function getCategory(age) {
  2. var category = "";
  3. switch (true) {
  4. case isNaN(age):
  5. category = "not an age";
  6. break;
  7. case (age >= 50):
  8. category = "Old";
  9. break;
  10. case (age <= 20):
  11. category = "Baby";
  12. break;
  13. default:
  14. category = "Young";
  15. break;
  16. };
  17. return category;
  18. }
  19. getCategory(5); // will return "Baby"

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

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

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

  1. function clone(object) {
  2. function OneShotConstructor(){};
  3. OneShotConstructor.prototype= object;
  4. return new OneShotConstructor();
  5. }
  6. clone(Array).prototype ; // []

四十二、一个HTML转义函数

  1. function escapeHTML(text) {
  2. var replacements= {"<": "<", ">": ">","&": "&", "\"": """};
  3. return text.replace(/[<>&"]/g, function(character) {
  4. return replacements[character];
  5. });
  6. }

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

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

避免这样的写法:

  1. var object = ['foo', 'bar'], i;
  2. for (i = 0, len = object.length; i <len; i++) {
  3. try {
  4. // do something that throws an exception
  5. }
  6. catch (e) {
  7. // handle exception
  8. }
  9. }

而使用:

  1. var object = ['foo', 'bar'], i;
  2. try {
  3. for (i = 0, len = object.length; i <len; i++) {
  4. // do something that throws an exception
  5. }
  6. }
  7. catch (e) {
  8. // handle exception
  9. }

四十四、为 XMLHttpRequests 设置超时。

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

  1. var xhr = new XMLHttpRequest ();
  2. xhr.onreadystatechange = function () {
  3. if (this.readyState == 4) {
  4. clearTimeout(timeout);
  5. // do something with response data
  6. }
  7. }
  8. var timeout = setTimeout( function () {
  9. xhr.abort(); // call error callback
  10. }, 60*1000 /* timeout after a minute */ );
  11. xhr.open('GET', url, true);
  12. xhr.send();

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

四十五、处理WebSocket超时

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

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

使用一个 timerID:

  1. var timerID = 0;
  2. function keepAlive() {
  3. var timeout = 15000;
  4. if (webSocket.readyState == webSocket.OPEN) {
  5. webSocket.send('');
  6. }
  7. timerId = setTimeout(keepAlive, timeout);
  8. }
  9. function cancelKeepAlive() {
  10. if (timerId) {
  11. cancelTimeout(timerId);
  12. }
  13. }

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

四十六、牢记,原始运算符始终比函数调用要高效。使用VanillaJS。

举例来说,不使用:

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

而用:

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

javascript实用技巧,js小知识的更多相关文章

  1. 【JavaScript实用技巧(二)】Js操作DOM(由问题引发的文章改版,新人大佬都可)

    [JavaScript实用技巧(二)]Js操作DOM(由问题引发的文章改版,新人大佬都可!) 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人 ...

  2. javascript实用技巧、javascript高级技巧

    字号+作者:H5之家 来源:H5之家 2016-10-31 11:00 我要评论( ) 三零网提供网络编程. JavaScript 的技术文章javascript实用技巧.javascript高级技巧 ...

  3. JavaScript 实用技巧和写法建议

    1.前言 从大学到现在,接触前端已经有几年了,感想方面,就是对于程序员而言,想要提高自己的技术水平和编写易于阅读和维护的代码,我觉得不能每天都是平庸的写代码,更要去推敲,去摸索和优化代码,总结当中的技 ...

  4. 第24篇 js小知识和“坑”

    前面说了说了js的相关知识,基本上除了语法外,把项目常用的知识做了一个梳理,现在说下js的其它方面的知识,这些知识不成体系,属于不理解对于一般开发没什么太多影响,但如果理解清楚,可以更好去开发. js ...

  5. Javascript开发技巧(JS中的变量、运算符、分支结构、循环结构)

    一.Js简介和入门 继续跟进JS开发的相关教程. <!-- [使用JS的三种方式] 1.HTML标签中内嵌JS(不提倡使用): 示例:<button onclick="javas ...

  6. 刚开始学习Javascript的一些基础小知识,从入门到崩溃,希望对大家有帮助(只适合初学者)

    一.简介 1.JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型,js不能操作文件. 重要的开始啦!!!!! 引入javascript: 行间js <d ...

  7. 零散的JS和node.js小知识

    JS的连续赋值和曾经出现的怪异情况 let a=1; let b=a=3; 如上的真实赋值过程 => a=1 => a=3 => b=3 => 一般来说,等号是从右向左赋值的 ...

  8. javascript小技巧-js小技巧收集(转)

    本文转载自:http://blog.csdn.net/ocean20/article/details/2498699 每一项都是js中的小技巧,但十分的实用! 1.document.write(&qu ...

  9. JavaScript 性能优化的小知识总结

    前言 一直在学习 javascript,也有看过<犀利开发 Jquery 内核详解与实践>,对这本书的评价只有两个字犀利,可能是对 javascript 理解的还不够透彻异或是自己太笨,更 ...

随机推荐

  1. 使用PopupWindow

    PopupWindow可以用来实现弹出任意位置的菜单,比Context Menu和Option Menu灵活性更高.Android中弹出一个PopupWindow基本有两个方法: 1 2 //Disp ...

  2. 3.创建基本的AngularJS应用

    1.1.模块 AngularJS引入了代表应用程序组件的模块的概念.模块提供命名空间,以基于模型的名称来引用指令,范围和其他组件.使得包装和再利用应用程序的部件更容易. AngularJS中,每个视图 ...

  3. 31 GroupSock(AddressString)——live555源码阅读(四)网络

    31 GroupSock(AddressString)——live555源码阅读(四)网络 31 GroupSock(AddressString)——live555源码阅读(四)网络 简介 Addre ...

  4. Python判断当前用户是否是root

    import osif os.geteuid() != 0:print "This program must be run as root. Aborting."sys.exit( ...

  5. AJAX 页面数据传递

    $.ajax({ //一个Ajax过程 type: "post", //以post方式与后台沟通 url: "personstockajax.php", //与 ...

  6. 常用浏览器user_agent大全

    PC端: safari 5.1 – MACUser-Agent:Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit ...

  7. 17.2---#字棋(CC150)

    牛客网的在线题.思路,比较简单.就是判断一下是否有连起来的1. public static boolean checkWon(int[][] board){ boolean res = false; ...

  8. 使用Grub Rescue恢复Ubuntu引导

    装了Ubuntu和Window双系统的电脑,通常会使用Ubuntu的Grub2进行引导. Grub2会在MBR写入引导记录,并将引导文件放在/boot/grub,破坏任意一项都会导致系统无法正常启动. ...

  9. 19. javacript高级程序设计-E4X

    1. E4X E4X是对ECMAScript的一个扩展, l 与DOM不同,E4X只用一个类型节点来表示XML中的各个节点 l XML对象中封装了对所有节点都有用的数据和行为.为了表示多个节点的集合, ...

  10. Greedy:The Water Bowls(POJ 3185)

    水池 题目大意:给定一个20的数组,全都是0和1,可以翻一个数改变成另一个数(0或者1),但是其左右两边的数都会跟着变为原来的相反数,问你怎么用最小的操作数使全部数变成0 这一题的:满足 1:翻转次序 ...