文档章节

早该知道的 7 个JavaScript 技巧

lotozhou
 lotozhou
发布于 2015/12/07 14:14
字数 3117
阅读 74
收藏 5
点赞 0
评论 0

简洁写法

象的简写
在过去,如果你想创建一个对象,你需要这样:

var car = new Object(); 
car.colour = 'red'; 
car.wheels = 4; 
car.hubcaps = 'spinning'; 
car.age = 4;

下面的写法能够达到同样的效果:

var car = { 
colour:'red', 
wheels:4, 
hubcaps:'spinning', 
age:4 
}

这样就简单多了,你不需要反复使用这个对象的名称。
这样 car 就定义好了,也许你会遇到 invalidUserInSession 的问题,这只有你在使用IE时会碰到,只要记住一点,不要右大括号前面写分号,你就不会有麻烦。

数组的简写

传统的定义数组的方法是这样:

var moviesThatNeedBetterWriters = new Array(
    'Transformers','Transformers2','Avatar','Indiana Jones 4');

简写版是这样:

var moviesThatNeedBetterWriters = [
    'Transformers','Transformers2','Avatar','Indiana Jones 4'];

对于数组,这里有个问题,其实没有什么图组功能。但你会经常发现有人这样定义上面的 car ,就像这样:

var car = new Array(); 
car['colour'] = 'red'; 
car['wheels'] = 4; 
car['hubcaps'] = 'spinning'; 
car['age'] = 4;

数组不是万能的;这样写不对,会让人困惑。图组实际上是对象的功能,人们混淆了这两个概念。

三元条件符号的简写

另外一个非常酷的简写方法是使用与三元条件符号。
你不必写成下面的样子:

var direction; 
if(x < 200){ 
   direction = 1; 
}
else { 
  direction = -1; 
}

你可以使用三元条件符号简化它:

var direction = x < 200 ? 1 : -1;

当条件为true 时取问号后面的值,否则取冒号后面的值。

用 JSON 形式存储数据

Douglas Crockford 发明了JSON 之后,一切全变了。
使用JSON,你可以使用JavaScript自有功能把数据存贮成复杂的格式,而且不需要再做其它的额外转换,直接可以访问使用。

JSON 是 “JavaScript Object Notation” 的缩写,它用到了上面提到的两种简写方法。 

如果你想描述一个乐队,你可能会像这样写:

var band = {
"name":"The Red Hot Chili Peppers",
"members":
  [
    {
       "name":"Anthony Kiedis",
       "role":"lead vocals"
     },
    {
       "name":"Michael 'Flea' Balzary",
       "role":"bass guitar, trumpet, backing vocals"
     },
    { 
       "name":"Chad Smith", 
       "role":"drums,percussion" 
     }, 
    {
       "name":"John Frusciante", 
       "role":"Lead Guitar" 
     } 
  ], 
"year":"2009" 
}

你可以在JavaScript里直接使用JSON,可以把它封装在函数里,甚至作为一个API的返回值形式。
我们把这称作 JSON-P ,很多的API都使用这种形式。
你可以调用一个数据提供源,在script代码里直接返回 JSON-P 数据:

<div id="delicious"></div>
<script> 
   function delicious(o){ 
   var out = '<ul>'; 
   for(var i=0;i<o.length;i++)
   {
       out += '<li><a href="' + o[i].u + '">' + o[i].d + '</a></li>'; 
   } 
   out += '</ul>'; 

   document.getElementById('delicious').innerHTML = out; 
   }
</script> 
<script src="#"></script>

这是调用 Delicious 网站提供的 Web service 功能,获得JSON格式的最近的无序书签列表。

基本上,JSON是最轻便的描述复杂数据结构的方法,而且它能在浏览器里运行。你甚至可以在PHP里用 json_decode() 函数来运行它。 

JavaScript的自带函数(Math, Array 和 String)

JavaScript里的math和String函数后,发现它们能极大的简化我的编程劳动。使用它们,你可以省去复杂的循环处理和条件判断。

例如,当需要实现一个功能,找出数字数组里最大的一个数时,我过去是这样写出这个循环的,就像下面:

var numbers = [3,342,23,22,124]; 
var max = 0; 
for(var i=0;i<numbers.length;i++)
{ 
   if(numbers[i] > max){ 
      max = numbers[i]; 
   } 
} 
alert(max);

不用循环也能实现:

var numbers = [3,342,23,22,124];
numbers.sort(function(a,b){ return b - a }); 
alert(numbers[0]);

事件委派

Web应用都是由事件驱动运转的。我喜欢事件处理,尤其喜欢自己定义事件。
它能使你的产品可扩展,而不用改动核心代码。
有一个很大的问题(也可以说是功能强大的表现),是关于页面上事件的移除问题。你可以对某个元素安装一个事件监听器,事件监听器就开始运转工作。
但页面上没有任何指示说明这有个监听器。因为这种不可表现的问题 (这尤其让一些新手头疼) ,以及像IE6这样的”浏览器“在太多的使用事件监听时会出现各种的内存问题,你不得不承认尽量少使用事件编程是个明智的做法。

于是事件委托就出现了。
当页面上某个元素上的事件触发时,而在 DOM 继承关系上,这个元素的所有子元素也能接收到这个事件,这时你可以使用一个在父元素上的事件处理器来处理,而不是使用一堆的各个子元素上的事件监听器来处理。

究竟是什么意思?这样说吧,页面上有很多超链接,你不想直接使用这些链接,想通过一个函数来调用这个链接,HTML代码是这样的:

<h2>Great Web resources</h2>
<ul id="resources">
   <li><a href="http://opera.com/wsc">Opera Web Standards Curriculum</a></li>
   <li><a href="http://sitepoint.com/">Sitepoint</a></li>
   <li><a href="http://alistapart.com/">A List Apart</a></li>
   <li><a href="http://yuiblog.com/">YUI Blog</a></li>
   <li><a href="http://blameitonthevoices.com/">Blame it on the voices</a></li>
   <li><a href="http://oddlyspecific.com/">Oddly specific</a></li> 
</ul>

常见的做法是通过循环这些链接,将每个链接上附加一个事件处理器:

(function(){
var resources = document.getElementById('resources');
var links = resources.getElementsByTagName('a');
var all = links.length; 

   for(var i=0;i<all;i++)
   {
      // Attach a listener to each link
      links[i].addEventListener('click',handler,false); 
   }; 
   function handler(e)
   { 
      var x = e.target; // Get the link that was clicked 
      alert(x);
      e.preventDefault(); 
   }; 
})();

我们用一个事件处理器也能完成这项任务:

(function(){
   var resources = document.getElementById('resources');
   resources.addEventListener('click',handler,false); 

   function handler(e)
   {
      var x = e.target; // get the link tha 

      if(x.nodeName.toLowerCase()== 'a')
      { 
         alert('Event delegation:' + x);
         e.preventDefault();
      }
   };
})();

因为点击事件就发生在这些页面元素里,你要做的就是比较它们的 nodeName,找出应该回应这个事件的那个元素。

 

免责声明:上面说的这两个关于事件的例子,在所有浏览器里都能运行,除了IE6,在IE6上你需要使用一个事件模型,而不是简单的W3C的标准实现。这也就是我们推荐使用一些工具包的原因。

这种方法的好处并不是仅限于把多个事件处理器缩减为一个。你想想,举个例子,你需要动态的往这个链接表里追加更多的链接。使用事件委托后,你就不需要做其它修改了;否则的话,你需要重新循环这个链接表,重新给每个链接安装事件处理器。

匿名函数和模块化

在JavaScript里最令人懊恼的事情是变量没有使用范围。任何变量,函数,数组,对象,只要不在函数内部,都被认为是全局的,这就是说,这个页面上的其它脚本也可以访问它,而且可以覆盖重写它。

解决办法是,把你的变量放在一个匿名函数内部,定义完之后立即调用它。
例如,下面的写法将会产生三个全局变量和两个全局函数:

var name = 'Chris'; 
var age = '34'; 
var status = 'single'; 

function createMember(){
  // [...] 
}

function getMemberDetails(){ 
  // [...] 
}

如果这个页面上的其它脚本里也存在一个叫 status 的变量,麻烦就会出现。
如果我们把它们封装在一个 myApplication 里,这个问题就迎刃而解了:

但是,这样一来,在函数外面就没有什么功能了。如果这是你需要的,那就可以了。

你还可以省去函数的名称:

(function(){ 
var name = 'Chris'; 
var age = '34'; 
var status = 'single'; 

   function createMember(){
     // [...]
   } 
   function getMemberDetails(){
     // [...]
   } 
})();

如果你想在函数外面也能使用里面的东西,那就要做些修改。

 为了能访问 createMember() 或 getMemberDetails(),你需要把它们变成 myApplication的属性,从而把它们暴露于外部的世界:

var myApplication = function()
{ 
  var name = 'Chris'; 
  var age = '34'; 
  var status = 'single'; 

  return{
    createMember:function(){
      // [...]
    },
    getMemberDetails:function(){
      // [...]
    }
  } 
}();

这被称作 module 模式或 singleton。

Douglas Crockford 多次谈到过这些,Yahoo User Interface Library YUI 里对此有大量的使用。但这样一来让我感到不便的是,我需要改变句式来使函数和变量能被外界访问。更甚者,调用时我还需要加上myApplication 这个前缀。所以,我不喜欢这样做,我更愿意简单的把需要能被外界访问的元素的指针导出来。这样做后,反倒简化了外界调用的写法:

var myApplication = function()
{ 
   var name = 'Chris'; 
   var age = '34'; 
   var status = 'single'; 

   function createMember(){ 
     // [...]
   } 

   function getMemberDetails(){
     // [...]
   } 

   return{
     create:createMember, 
     get:getMemberDetails
   }
}();

我把这个称作 “revealing module pattern.”

可配置化

一旦我把所写的JavaScript代码发布到这个世界上,就有人想改动它,通常是人们想让它完成一些它本身完成不了的任务—但通常也是我写的程序不够灵活,没有提供用户可自定义的功能。

通常情况下这是你编程过程中的最后一步要做的事情。我把这些集中表现在了一个例子里: “Five things to do to a script before handing it over to the next developer.”

实际上,你也希望你的代码能够让人们很方面的使用,并且根据他们各自的需要进行一些改动。
如果你实现了这个功能,你会少收到一些抱怨你的脚本的人发送给你的让你困惑的邮件,这些信件会告诉你,有人修改了你的脚本,而且很好用。

 

与后台交互

在这么多年的编程经历中,我所领悟到的一个重要的事情就是,JavaScript是一个很优秀的开发界面交互的语言,但如果用来处理数字或访问数据源,那就有点使不上劲了。

最初,我学习JavaScript,是用来替代Perl的,因为我很讨厌非要把代码拷贝到 cgi-bin 文件夹下才能使Perl运行。
后来,我明白了应该使用一种后台工作的语言来处理主要的数据,而不能什么事情都让JavaScript去做。更重要的是我们要考虑安全性和语言特征。

如果我访问一个Web service, 我可以获取到JSON-P 格式的数据,在客户端浏览器里我把它做各种各样的数据转换,但当我有了服务器时,我有了更多的方法来转换数据,我可以在Server端生成JSON或HTML格式的数据返回给客户端,以及缓存数据等操作。
如果你事先了解了并准备了这些,你会长期收益,省去了很多头疼的时间。


编写适用各种浏览器的程序是种浪费时间,使用工具包吧!

在我最初开始搞Web开发时,在访问页面时,究竟是使用 document.all 还是使用 document.layers 的问题上痛苦的挣扎了很久。
我选择了 document.layers,因为我喜欢任何层都是自己的document的思想 (而且我写了太多的 document.write 来生成元素)。
层模式最终失败了,于是我开始使用 document.all
当Netscape 6 公布只支持 W3C DOM 模型时,我很高兴,但其实用户并不关心这些。
用户只是看见这种浏览器不能显示大多数浏览器都能正常显示的东西—这是我们编码的问题。
我们编写了短视的代码,只能运行在当前的环境下,而不幸的是,我们的运行环境却在不停的改变。

我已经浪费了太多的时间来处理对各种浏览器各种版本兼容的问题。
善于处理这类问题提供了我一个好的工作机会。但现在我们不必在忍受这种痛苦了。

一些工具包,例如 YUI, jQuery 以及 Dojo 都能够帮我们处理这类问题。
它们通过抽象各种接口实现来处理浏览器的各种问题,像版本不兼容,设计缺陷等,把我们从痛苦中解救出来。
除非你要测试某个Beta版的浏览器,千万不要在自己的程序里添加修正浏览器的缺陷的代码,因为你很有可能当浏览器已经修改了这个问题时,你却忘了删除你的代码。

另一方面,完全依赖于工具包也是个短视的行为。工具包可以帮你快速的开发,但如果你不深入理解JavaScript,你也会做错事。



© 著作权归作者所有

共有 人打赏支持
lotozhou
粉丝 8
博文 51
码字总数 51524
作品 0
苏州
程序员
怪异的JavaScript系列(二)

译者按: JavaScript有很多坑,经常一不小心就要写bug。 原文: What the f*ck JavaScript? 译者: Fundebug 为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学...

Fundebug ⋅ 04/25 ⋅ 0

学习Javascript的8张思维导图

分别归类为:  javascript变量  javascript运算符  javascript数组  javascript流程语句  javascript字符串函数  javascript函数基础  javascript基础DOM操作  javascript正则表达式...

thinkyoung ⋅ 2014/09/23 ⋅ 0

怪异的JavaScript系列(三)

译者按: JavaScript有很多坑,经常一不小心就要写bug。 原文: What the f*ck JavaScript? 译者: Fundebug 为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学...

Fundebug ⋅ 04/26 ⋅ 0

5 分钟掌握 JavaScript 实用窍门

简评:一开始 JavaScript 只是为网页增添一些实时动画效果,现在 JS 已经能做到前后端通吃了,而且还是年度流行语言。本文分享几则 JS 小窍门,可以让你事半功倍 ~ 1. 删除数组尾部元素 一个...

⋅ 06/07 ⋅ 0

怪异的JavaScript系列(一)

译者按: JavaScript有很多坑,经常一不小心就要写bug。 原文: What the f*ck JavaScript? 译者: Fundebug 为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学...

Fundebug ⋅ 04/24 ⋅ 0

15个必备的javascript小技巧,看的懂是入门,全会写就是大神

1、变量转换 看起来很简单,但据我所看到的,使用构造函数,像Array()或者Number()来进行变量转换是常用的做法。始终使用原始数据类型(有时也称为字面量)来转换变量,这种没有任何额外的影...

急速奔跑中的蜗牛 ⋅ 06/06 ⋅ 0

面向对象,更适合JavaScript

面向对象程序设计是软件开发中一个很庞大很复杂的话题,它并不是仅仅学会类、继承、封装、多态这些面向对象编程语法元素就表示掌握的,这些语法元素只是实现面向对象程序的工具, 就像砖块、...

陈宏鸿 ⋅ 05/07 ⋅ 0

深入了解React.js的JSX

JSX 是React 为JavaScript 语法带来的可选扩展,用于在JavaScript 代码中编写声明式XML 风格语法。 对于Web 项目而言,React 的JSX 提供了一组类似于HTML 的XML 标签,但在其他使用场景中,会...

紫霞等了至尊宝五百年 ⋅ 06/01 ⋅ 0

精读《JS 引擎基础之 Shapes and Inline Caches》

1 引言 本期精读的文章是:JS 引擎基础之 Shapes and Inline Caches 一起了解下 JS 引擎是如何运作的吧! JS 的运作机制可以分为 AST 分析、引擎执行两个步骤: JS 源码通过 parser(分析器)...

黄子毅 ⋅ 今天 ⋅ 0

Js如果没有了getDay,怎么获取某天是星期几?

昨天在《枕边算法书》看到一个撩妹技巧:“美丽的女士,请您随便说一个年份,我会猜出当年的情人节是星期几”。那这哥们是如何快速的算出的呢?书中提到了,其原理就是设立一个基点,根据星期...

tryzf ⋅ 06/03 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JPA入门,配置文件的设置

<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http......

码农屌丝 ⋅ 10分钟前 ⋅ 0

Java基础——面向对象和构造器

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。 静态成员介绍 为什么要有静态成员?静态成员用来...

凯哥学堂 ⋅ 12分钟前 ⋅ 0

vmware中Centos 7 linux的LVM磁盘扩容

系统是RHEL7(centos7差不多一样) 关闭系统,在vmware、设置、硬盘、扩展、输入数字大于当前系统内存、点击扩展。 开机再查看磁盘信息 fdisk -l 注意:可以看出sda磁盘增加了,但是根目录还...

gugudu ⋅ 23分钟前 ⋅ 0

JAVA线程sleep和wait方法区别

昨天面试,突然被问到sleep 和 wait的区别,一下子有点蒙,在这里记一下,以示警戒。 首先说sleep,sleep就是正在执行的线程主动让出cpu,cpu去执行其他线程,在sleep指定的时间过去后,cpu...

徐玉强 ⋅ 24分钟前 ⋅ 0

vuex学习--模块

随着项目复杂性增加,共享状态也越来越多。需要对转态操作进行分组,分组后在进行分组编写。学习一下module:状态管理器的模块组操作。 首先是声明: const moduleA={ state,mutations,g...

大美琴 ⋅ 27分钟前 ⋅ 0

Selenium 简单入门

安装 pip install selenium 驱动下载 https://chromedriver.storage.googleapis.com/index.html 下载最新的驱动,放入path中,可以放入Python的scripts目录下,也可以放入Chrome安装目录,并...

阿豪boy ⋅ 28分钟前 ⋅ 0

292. Nim Game - LeetCode

Question 292. Nim Game Solution 思路:试着列举一下,就能发现一个n只要不是4的倍数,就能赢。 n 是否能赢1 true2 true3 true4 false 不论删除几,对方都能一把赢5 t...

yysue ⋅ 58分钟前 ⋅ 0

6.5 zip压缩工具 6.6 tar打包 6.7 打包并压缩

zip压缩工具 zip命令可以压缩目录和文件,-r 压缩目录。 zip使用方法 zip 1.txt.zip 1.txt //压缩文件 zip -r 123.zip 123/ //压缩目录 unzip 1.txt.zip //解压 unzip 123.zip -d /root/456...

Linux_老吴 ⋅ 今天 ⋅ 0

react-loadable使用跳坑

官方给react-loadable的定义是: A higher order component for loading components with dynamic imports. 动态路由示例 withLoadable.js import React from 'react'import Loadable fro......

pengqinmm ⋅ 今天 ⋅ 0

记录工作中遇到的坑

1、ios safari浏览器向下滚动会触发window resize事件

端木遗风 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部