JS学习(一)
JS学习(一)
背景描述:
JavaScript是世界上最流行的脚本语言,因为你在电脑、手机、平板上浏览的所有的网页,以及无数基于HTML5的手机App,交互逻辑都是由JavaScript驱动的。
简单地说,JavaScript是一种运行在浏览器中的解释型的编程语言。
那么问题来了,为什么我们要学JavaScript?尤其是当你已经掌握了某些其他编程语言如Java、C++的情况下。
简单粗暴的回答就是:因为你没有选择。在Web世界里,只有JavaScript能跨平台、跨浏览器驱动网页,与用户交互。
Flash背后的ActionScript曾经流行过一阵子,不过随着移动应用的兴起,没有人用Flash开发手机App,所以它目前已经边缘化了。相反,随着HTML5在PC和移动端越来越流行,JavaScript变得更加重要了。并且,新兴的Node.js把JavaScript引入到了服务器端,JavaScript已经变成了全能型选手。
JavaScript一度被认为是一种玩具编程语言,它有很多缺陷,所以不被大多数后端开发人员所重视。很多人认为,写JavaScript代码很简单,并且JavaScript只是为了在网页上添加一点交互和动画效果。
但这是完全错误的理解。JavaScript确实很容易上手,但其精髓却不为大多数开发人员所熟知。编写高质量的JavaScript代码更是难上加难。
一个合格的开发人员应该精通JavaScript和其他编程语言。如果你已经掌握了其他编程语言,或者你还什么都不会,请立刻开始学习JavaScript,不要被Web时代所淘汰。
--- 廖雪峰js教程
1.ES6新特性
ES6的模板字符串写法令我很感兴趣。
在没有ES6新特性之前,使用js拼接字符串是这样的:
var name = '小明';
var age = 20;
var message = '你好, ' + name + ', 你今年' + age + '岁了!';
alert(message);
如果你想换行,还要加上转义字符:
var name = '小明';
var age = 20;
var message = '你好, \n' + name + ', 你今年\n' + age + '岁了!';
alert(message);
可ES6允许你使用以下写法:
var name = '小明';
var age = 20;
alert(`你好
${name},你今年
${age}岁了`);
这一下就让代码极其清晰易懂。
以上只是一个简单的事例,还看不出它的好处。我举一个我工作中遇到的问题,这是我接手的之前人写的代码(安全起见,变量名全部换为xx):
var xx = data.xx.id;
var xx = data.xx;
var xx = data.xx;
var result = '<a class="tdbut" onclick="xx(\'' + id + '\',\'' + workFlowId + '\');">查看(' + xx + ')</a> ' +
'<input type="button" class="tdbut" value="打印" onclick="xx(\'' + id + '\')"/> ';
if (xx == 10 && xx == xx) {
result = result +
'<a class="tdbut" onclick="xx(\'' + id + '\',\'' + xx + '\');">派发</a> ';
}
if (xx == 20 && xx == xx && xx == 0) {
result = result +
'<a class="tdbut" onclick="xx(\'' + id + '\',\'' + xx + '\');">派发</a> ';
}
这是一个在jsp中使用ajax请求服务器,并根据返回结果在页面中添加按钮的方法。
这个玩意能看懂啥意思,但是这些拼接看起来让人恶心,写这种玩意的时候,需要注意太多的单引号双引号匹配,少写一个就要出错。想象一下,假如你要修改这个函数,需要增加一个参数,是一个多么恶心的事情。更离谱的是:像这种代码有几百行!!
如果使用ES6,可以改成这样:
var xx = data.xx.id;
var xx = data.xx;
var xx = data.xx;
var result = `<a class="tdbut" onclick="xx('${id}', '${xx}')">查看('${name}')</a> `;
if (xx == 10 && xx == xx) {
result = result +`<a class="tdbut" onclick="xx('${id}', '${xx}')">派发('${name}')</a> `;
}
if (xx == 20 && xx == xx && xx == 0) {
result = result +`<a class="tdbut" onclick="xx('${id}', '${xx}')">派发('${name}')</a> `;
}
瞬间感觉舒服了。
不要感觉代码能正常运行就好了,写的好不好看无所谓。每一份代码大概率需要迭代和维护的,你开发的时候多花一份心思写一份结构清晰、风格优美的代码,可以为你日后维护升级剩下大量的精力。
有时候你为了早点下班,匆匆忙忙写了一份未经思考的代码。也许现在轻松,但是高耦合、混乱的逻辑、恶劣的编码风格一定会让你在日后的工作中付出成倍的代价。
实在忍不住吐槽一下以下编码风格,你们是吃奥利给吃多了吗?:
- 一个类写几千行,一个方法写上大几百行
当你维护这种狗屁玩意的时候,你需要花一两个小时去看他到底写了个什么狗屁逻辑。
- 变量名使用拼音或者英文拼音结合
你TM活在10年前搞开发呢?你写的这种狗屁变量很难让人理解这个玩意。TM英语不好,你不会搜索一下?
- jsp中js代码与EL表达式混着写:
<script>
var a = ${id}
</script>
呵呵,告诉你,你把数据库连接写在jsp中都行,你怎么不写?springmvc框架分离的已经很完美了,你就是要强行增加耦合!就是要让代码看的麻烦!就因为你懒得增加一个标识。
- 魔法值和无穷无尽的if嵌套,尤其是当这两者结合到一起的时候,短短几行代码就会花费你一上午的时间去找这些变量。
public void test(int a, int b, int c){
if(a == 1){
if(b == 1){
//TODO
}else if(b == 2){
if(c == 2){
//TODO
}else{
//TODO
}
}else if(b == 3){
//TODO
}else{
if(c == 3){
//TODO
}else{
//TODO
}
}
}
}
上面这个代码我真的遇到过,我真是佩服他在提高代码阅读难度上的强悍能力。奥利给吃多了的典型。兄弟们,你们觉得以下的代码,写起来很麻烦吗:
private static final int PROJECT_NUM = 1;
private static final int SUBJECT_NUM = 2;
private static final int PEOPLE_NUM = 3;
public void test(int projectNum, int subjectNum, int peopleNum){
if(projectNum != PROJECT_NUM){
//TODO
return;
}
if(subjectNum == PROJECT_NUM){
//TODO
return;
}
if(subjectNum == SUBJECT_NUM){
if(peopleNum == SUBJECT_NUM){
//TODO
return;
}
if(peopleNum != SUBJECT_NUM){
//TODO
return;
}
}
if(subjectNum == PEOPLE_NUM){
//TODO
return;
}
if(peopleNum == PEOPLE_NUM){
//TODO
return;
}else{
//TODO
return;
}
- 爱用try...catch,但是不捕获异常
求你了,做个人吧。你不用try...catch,至少还能由系统捕获异常,你写个try不处理异常,出了问题就得一行行的debug。
2.ES6兼容性
ES6新特性很好很美妙,遗憾的是它提出的较晚,一些浏览器不兼容他:没错就是你,终极恶心浏览器IE系列。我们项目都要求兼容IE9及以上,我就得研究一手ES6如何兼容IE。
参考以下博客:
[babel通过script标签引入无法解决低版本的ie兼容es6的问题(非解决方案,谈下遇到的坑)]
主要记录下我的使用体验:
2.1执行顺序
浏览器解析js都是顺序执行的,但是如果你的html中既有普通的js代码块,又有ES6代码块:
<script src="browser.min.js"></script>
<script>
alert('before');
</script>
<script type="text/babel">
const label = `张三爱`;
function test(){
var name = '李四';
const Name = `张三爱${name}`;
alert(Name);
}
test();
</script>
<script>
alert('after');
</script>
按照写的顺序,我以为应该是:
打印(before)---> 打印(张三爱李四) ---> 打印(after)
但实际的执行情况是,type="text/babel"的代码块会在所有普通代码块执行之后执行:
打印(before)---> 打印(after) ---> 打印(张三爱李四)
所以兄弟们如果想在自己的旧项目中兼容ES6,需要考虑这个问题。
2.2变量范围
-
在js中,变量的定义并不是以代码块作为作用域的,而是以函数作为作用域。也就是说,如果变量是在某个函数中定义的,那么,它在函数以外的地方是不可见的。但是,如果该变量是定义在if或者for这样的代码块中,它在代码块之外是可见的。
-
在js中,术语“全局变量”指的是定义在所有函数之外的变量(也就是定义在全局代码中的变量),与之相对的是“局部变量”,所指的是在某个函数中定义的变量。其中,函数内的代码可以像访问自己的局部变量那样访问全局变量,反之则不行:
<script>
var label = '张三爱';
alert('before');
</script>
<script>
alert('after');
alert(label);
</script>
像这种就可以正常执行。
但是使用了babel解决兼容性问题的代码作用域就会局限在代码块中(我自己尝试的,没有找到官方说法),像以下代码:
<script src="browser.min.js"></script>
<script type="text/babel">
const label = `张三爱${name}`;
function test(){
var name = '李四';
const Name = `张三爱${name}`;
alert(Name);
}
test();
</script>
<script type="text/babel">
alert('before');
test();
</script>
<script type="text/babel">
alert('after');
alert(label);
</script>
label常亮和test()函数是无法在其他代码块中调用的。
上述结果可能和babel重新编译代码有关,真正的原因目前没有深入探究。
2.3和后端渲染语法冲突
没错,ES6使可以使用${}拼接字符串,这显然和jsp的EL表达式冲突,也和freemaker冲突。为了避免这个冲突,在jsp中,你就得写这样写:
var data = 'xx';
var messag = `操作成功,${'${data}'}!`;
这样看起来也很nc,而且增加了耦合,实在是。。。。。。
3总结
鉴于上述缺陷,我还是没有在项目中使用这个新特性。但是这方面的知识不能放弃学。
有以下四个原因:
- 随着浏览器的更新迭代,支持ES6必然成为主流
- 如果启动一个新项目,可以使所有代码块都使用babel,可以避免缺陷2.1
- 前后端分离的项目,可以避免缺陷2.3
- 兼容ES6还有其他方法,我目前只尝试了babel,还没研究缺陷2.2如何解决。。。。。。

浙公网安备 33010602011771号