Javascript Tips(2)
继续讲解javascript的一些小技巧及注意事项。
- 10. if else vs switch
- 11. 自定义Title tooltip
- 12. FireBug console type
- 13.代码性能测试(测试javascript用时)
- 14. Apply 、 Call用法
- 15. Callbacks 可以定义不同的对象
- 16. 继承相关
- 17. 闭包
- 18.javascript作用域
- 19.event.srcElement 与 Event.target
- 20. javascript的比较符
- 21. javascript中 逗号 与 分号 区别
- 22. $(this) 与 this
- 23.判断是否为数字的最快最准确方法
- 24. null 和 0
- 25. isNaN 与 Type of
- 26.自定义事件
- 27. break 、 continue、 return 区别
- 28.判断javascript对象是否存在
- 29. Promise 异步编程
- 30. 生成唯一id
- 31. 不要使用 for…in 来遍历数组
- 32. className VS classList
10. if else vs switch
switch(true) {
case (y < 20):
//
break;
case (y < 60):
//
break;
case (y < 130):
//
break;
}
相当于:
if (y < 20) {
// ...
} else if (y < 60) {
// ...
} else if ( y < 130) {
// ...
}
switch
提供了另一种写法,可以在case中添加表达式。 但测试比较看,if else 的效率更高。
当然,还有一种更加简洁的方法,如果为了得到一个变量,直接用二元表达式即可(该表达式也可以添加多个):
var browser = isChrome ? "chrome" :
isSafari ? "safari" :
isFirefox ? "firefox" :
null;
参考:
11. 自定义Title tooltip
思路: 先获取 Title
的值,再删除Title
属性, 然后自定义tooltip
$(document).ready(function() {
$('[title]').mouseover(function () {
$this = $(this);
$this.data('title', $this.attr('title'));
// Using null here wouldn't work in IE, but empty string will work just fine.
$this.attr('title', '');
}).mouseout(function () {
$this = $(this);
$this.attr('title', $this.data('title'));
});
});
12. FireBug console type
Color Coding:
console
.log
.info
.debug
.warn
.error
上述输出,支持占位符。如
console.log('%d is %s',12.3,'xxxx')
12 is xxxx
Timing and profiling:
console.time("timing foo")
console.timeEnd("timing foo")
参考:firebug log
13.代码性能测试(测试javascript用时)
var t0 = performance.now();
doSomething();
var t1 = performance.now();
console.log("Call to doSomething took " + (t1 - t0) + " milliseconds. ");
14. Apply 、 Call用法
作用:
① 定义一个方法,给另一个处于不同的作用域的对象用。
在javascript OOP
中,我们经常会这样定义:
function cat(){
}
cat.prototype={
food:"fish",
say: function(){
alert("I love "+this.food);
}
}
var blackCat = new cat;
blackCat.say();
但是如果我们有一个对象whiteDog = {food:"bone"}
, 我们不想对它重新定义say
方法,那么我们可以通过call
或apply
用blackCat的say
方法:
blackCat.say.call(whiteDog);
所以,可以看出call
和apply
是为了动态改变this
而出现的,当一个object没有某个方法,但是其他的有,我们可以借助call
或apply
用其它对象的方法来操作。
② 使用一个方法,定义不同的上下文
//定义一个人,名字为jack
var jack = {
name : "jack",
age : 26
}
//定义另一个人,名字为abruzzi
var abruzzi = {
name : "abruzzi",
age : 26
}
//定义一个全局的函数对象
function printName(){
return this.name;
}
//设置printName的上下文为jack, 此时的this为jack
print(printName.call(jack));
③ Apply 、Call区别
第一个参数相同,
后续参数:
Apply为数组 Apply(object, [arguments1, ...]
,
Call为对象 Call( object, arguments1, ... )
15. Callbacks 可以定义不同的对象
// Callbacks测试 定义不同的callbacks对象,互不影响
var A = $.Callbacks(), B= $.Callbacks();
var x1 = function(u,s){
console.log("111h:"+u+"\n"+s);
}
var x2 = function(u){
console.log("hahhh:"+u);
}
A.add(x1);
B.add(x2);
B.add(x1);
A.fire('ss','jjjj'); // 只输出 x1的
B.fire('BBBB','AAAA') // 输出x2、x1的
16. 继承相关
原型继承:
$.fn.xxx = ...
Create.Object( ... );
17. 闭包
注意下面的例子:
var x = 100; //定义的全局变量
function d1(){
var x= 1;
function d2(){
return x++;
}
return d2; //加括号与不加括号是不同的。 如果加了括号, d2(),代表执行该函数。 不加,则只是返回函数,并不执行
}
var dd = d1(); //此时代表,先执行d1()函数,返回d2 给了dd。
dd(); //output: 1 此代表,执行d2函数, 即 d2()。 由于d2函数与 x 在同一作用域(d1)下,因此x被保留在内存中。
dd(); //output: 2 全局的x并不会收影响
function func(){
var result = [];
for (var i = 0; i < 10; i++) {
result[i] = function() {
return i;
}
}
return result;}
var funcc = func();
funcc[8]() //??
// 怎么打印出 1,2,3,4,5,6,7,8
改为如下方式,即可。
function func(){
var result = [];
for (var i = 0; i < 10; i++) {
result[i] = (function(i) {
return function(){
return i;
};
})(i)
}
return result;
}
var funcc = func();
funcc[8]() //??
使用代理(javascript循环添加事件):
function delegate(fn,params,obj){
return function(){
fn.call(obj||window,params);
}
}
18.javascript作用域
JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里.
19.event.srcElement 与 Event.target
- event.srcElement in Internet Explorer
- event.target in most other browsers.
20. javascript的比较符
== 与 === 区别: ==只比较值相等, === 对比 值 + 类型 相等
注: 数组 与 对象, 不能直接比较。
如需比较相等,一般需转换为字符串。 JSON.stringify(obj1) = JSON.stringify(obj2)
21. javascript中 逗号 与 分号 区别
逗号: 连续定义, 逗号运算符会计算前后两个表达式,然后返回右边表达式的计算结果
分号:连接前后两个语句。仍返回最后一个表达式的结果。
场景:
逗号是用来分隔参数什么的,而分号是用来分隔语句的。
注:
对象字面量间,只能用 逗号, 而不能用分号。
22. $(this) 与 this
通常,$(this)
是把当前对象,转换成 jquery
的对象。如果含有多个相同的 dom,则会返回一个数组。
this
为当前作用域的对象。
$(this)[0] === this
$("#myDiv")[0] === document.getElementById("myDiv");
23.判断是否为数字的最快最准确方法
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
24. null 和 0
null 和 0 做 if 判断时,都会返回 false。 如何区分?
用parseInt( n ) === n
即可 。
或 typeof n === 'number'
25. isNaN 与 Type of
用于判断是否为Number时, type of n == 'number'
的效率 要比 isNaN
高很多。
但type of NaN
也会返回 ‘number’
26.自定义事件
用on \ bind 绑定一个事件, 在用 trigger触发。 目的:将订阅者 与 发布者 解耦
27. break 、 continue、 return 区别
break: 跳出循环
continue: 跳出这次
return: 跳出整个
一个Function中,一旦遇到 Return,则会终止执行,不管在嵌套在循环内还是if内。
28.判断javascript对象是否存在
1. 如果只判断对象是否存在,推荐使用第五种写法。
if (typeof myObj == "undefined") {
var myObj = { };
}
2. 如果除了对象是否存在,还要判断对象是否有null值,推荐使用第一种写法。
if (!myObj) {
myObj = { };
}
29. Promise 异步编程
目的: 解决ajax请求,用请求后的数据再去请求,这种联调的方式导致的异步问题及不清晰代码导致的不易读问题
形式:
getData(xxx).then(do something).then(do something)
用Promise执行的ajax顺序请求,看起来比多重嵌套的异步写法更易读:
var getData1 = $.ajax('/json1');
var getData2 = function(data1){
return $.ajax('/json2?'+data1);
};
getData1
.then(getData2)
.then(function(data2){
console.log('Get', data2);
});
原理(利用原型链):
var getData = function(){};
getData.prototype.then = function(){};
30. 生成唯一id
/**
powred by mOxie
当前时间戳+五位随机数,唯一性99.99% (除非两个人在同一毫秒内获取到0~65535间相同的随机数)
@method guid
@static
@param {String} prefix to prepend (by default 'o' will be prepended).
@method guid
@return {String} Virtually unique id.
*/
var guid = (function() {
var counter = 0;
return function(prefix) {
var guid = new Date().getTime().toString(32), i;
for (i = 0; i < 5; i++) {
guid += Math.floor(Math.random() * 65535).toString(32);
}
return (prefix || 'o_') + guid + (counter++).toString(32);
};
}());
31. 不要使用 for…in 来遍历数组
for...in...
本是用来遍历对象的,且使用此方法,会把对象原型链下的所有属性都会遍历一遍。如果只想得到对象本身的属性,可以用下述方法:
var obj = {a:1, b:2};
Object.setPrototypeOf(obj, {c:3});
for (var prop in obj) {
if( obj.hasOwnProperty( prop ) ) {
console.log(obj[prop]); // 只会输出 1, 2
}
}
// 亦可使用 Object.getOwnPropertyNames() 获取对象本身的所有属性
Object.getOwnPropertyNames(obj) // ['a','b']
之所以不建议用它来遍历数组,是因为数组具有顺序性,使用 for…in 不能保证数组的顺序性。建议使用 for循环, Array.prototype.forEach(), 或者ES6新方法 for…of
32. className VS classList
给DOM添加类名有两种方法:
element.className = "foo bar";
或者
element.classList.add('foo');
element.classList.add('bar');
而经测试,classList 由于不会因为重新计算dom而耗费多余性能,其要比 className 要快,这在添加多个元素的动画效果时,会非常明显。但目前只支持到IE10+。测试结果可看 jsPerf