JavaScript红色警戒

JS红色警戒

JS有很多让人迷惑的地方,一起来看看吧。

with

with可以扩展作用域链,建议永远不要使用它。我们来看看这些列子。

案例1

正常用法

function People(name){
    this.name = name;
    this.eat = function(){
        console.log(this.name+"要吃饭");
    }
}
var me = new People("xiaohu");

with(me){
    console.log(name);//可以省略me.
    eat();//可以省略me.
}

看起来很方便的样子。

with让阅读代码的人很疯狂

看看下面的代码

with(me){
    console.log(name);
    eat();
    play=function(){//如果是省略了me.,那么play应该定义在对象me中
        console.log(this.name);
    }
    nickName="xiao" + name;//如果是省略了me.,那么nickName应该定义在对象me中
}

我们运行一下就知道,两个变量变成了全局变量。

案例2

正常用法

function People(name){
    this.name = name;
    this.property={
        wallet:{
            banknote:1000,
            coin:20,
            salary:9
        }
    };
    this.eat = function(){
        console.log(this.name+"要吃饭");
    }
}
var me = new People("xiaohu");
var salary=2000;
with(me.property.wallet){//好像很方便啊
    banknote+=salary;//等等,salary到底是me.property.wallet还是哪儿的啊?
    console.log(banknote);
}

with让阅读代码的人很疯狂

我们还是用其他方法吧。

var salary=2000;
var wallet = me.property.wallet;
wallet.banknote+=salary;
console.log(wallet.banknote);

像这样缓存起来就很好var wallet = me.property.wallet;

eval

eval容易出错

JS的eval可能会使代码不清晰,影响调试和性能,应该避免使用。看看下面这段代码。

function Workers(){
    this.assignment=function assignment(who, number){
        eval("this.work" + who + "='finish task:"+number+"'");
    }
}
var workers = new Workers();
for (var i = 0; i < 5; i++) {
    workers.assignment(i,i);
}

这段代码给工人分配工作,在对象workers创建很多的属性,eval实际上想执行这样的语句workers.work1='finin task:1'。在参数一切正常的情况下是可以很好的工作的,但是这个函数是很容易出错的。
像下面这样传入空格,“'”等字符串的结束标记,都会让eval尝试运行的语句是不合法的,非常容易出错,也不容易调试。

workers.assignment("1   1","'");

eval最常见的错误就是像上面这样给对象加很多属性,其实用数组就可以很好的实现同样的功能。看看下面的代码。

function WorkersBetter(){
    this.workers=[];
    this.assignment=function assignment(name, task){
        //TODO: 检查数组越界......
        var obj ={name:name,task:task};
        this.workers.push(obj);
    }
}
var workersBetter = new WorkersBetter();

for (var i = 0; i < 3; i++) {
    workersBetter.assignment(i,"task"+i);
}

用eval容易被注入代码

看看这段代码,你只想赋值,弹出了对话框

workers.assignment("1","';alert('xiaohu');'");

在看看用eval解析json字符串的用法。同样这样也会让人注入代码,而且性能不好。

var jsonString='{"task":"write better javascript!"}';
var json = eval('('+jsonString+')');
console.log(json);

正确的做法应该用专门解析json的函数或者第三方库

console.log(JSON.parse(jsonString));

括号

条件判断应该加括号,并且成对出现,但是就是有人喜欢节省点,这样真实坑死队友啊。看看下面这样的代码

var isGoodCoder=false;
var salary=0,vacation=0;
if(isGoodCoder)
    salary=10000;
    vacation=30;

上面的vacation=30;已经不在if的控制范围里面了,好一些的写法应该这样

if(isGoodCoder){
    salary=10000;
    vacation=30;
}else{
    salary=1000;
    vacation=5;
}

数字问题

精度问题

程序并不能精确的保存和运算浮点数(小数)。我们看看JS如何处理这种情况。

0.1 + 0.2
=>0.30000000000000004

可以看到多出了0.00000000000000004,如果我们要用==或者和别的数字做运输,就会有问题。使用toFixed保存精度。

(0.1 + 0.2).toFixed(1);
=>"0.3"

虽然toFixed处理了精度问题,但是却返回了字符串,还要用parseFloat处理一下

parseFloat((0.1 + 0.2).toFixed(1));

parseFloat,parseInt可以从字符串中解析出数字。不过只能解析出以数字开头的字符串。
看一下下面的代码。

parseFloat("2.333是xiaohu的零用钱");//=>2.333
parseFloat("xiaohu的零用钱为2.333");//=>NaN

进制转换

parseInt(string, radix);

radix
一个2到36之间的整数值,用于指定转换中采用的基数。比如参数"10"表示使用我们通常使用的十进制数值系统。总是指定该参数可以消除阅读该代码时的困惑并且保证转换结果可预测。当忽略该参数时,不同的实现环境可能产生不同的结果。

看看如下代码:

parseInt(021);//=>17,八进制2*8^1+1*8^0=17
parseInt(021,10);//=>17,貌似第一个参数指定了进制,第二个参数没啥用处?
parseInt("021");//老得js标志和新的标准不一样,新的标准会返回21
parseInt("021",10);//=>21,这种方式才是最安全。

parseInt("021",10);是最好的。

判断是否是数字

typeof data === "number"可以判断一个变量是否是number类型。好像情况已经很简单了。但是JS有一个NaN,表示不是一个数字。但是typeof NaN === "number"却返回true。所以我们最好使用下面这个代码判断是否是数字,来处理这个特殊情况。

function isNumber(data){
    return ( typeof data === "number" 
        && !isNaN(data) ); 
}

强制转换

var hasAge = !!age;  

这为啥要写2个‘!’ ?
实际上!!age === Boolean(age),所以!!相当于强制转换成Boolean类型了。
另外这样也可以强制转换

var a = '12';
//+a就是数字12.

想了解强制转换的更多细节可以查看Javascript 强制类型转换函数

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容