初学Javascript

Author Avatar
tanglijun 8月 18, 2015

你否是了解 javascript 呢?那你是否对这些知识了如指掌呢?

简化代码

过去,当我们需要创建一个对象时,我们会这样写

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'
]

对于数组,还有关联数组这样一个特别的东西。 你会发现很多代码是这样定义对象的:

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;

条件为 ture 执行 ‘?‘ 后面的内容,否则执行 ‘:‘ 后面的内容。

JSON 数据格式

JSON 是 Javascript Object Notation 的缩写,是 Douglas Crockford 发明的一种轻量级数据交换格式。使用 JSON ,我们可以存储各种复杂的数据并且不需要进行额外的转换。

例如,想要存储一个乐队的信息

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 。因此利用 JSON 原生支持 javascript ,我们可以解决跨域问题。这种技术叫做 JSON-P

<div id="delicious"></div>
<script>
  function delicious(o) {
    var out = '<ul>';

    for (var i = 0; i < o.length; i += 1) {
      out += '<li><a href="' + o[i].u + '">' + o[i].d + '</a></li>';
    }

    out += '</ul>';

    document.getElementById('delicious').innerHTML = out;
  }
</script>
<script src="http://feeds.delicious.com/v2/json/codepo8/javascript?count=15&callback=delicious"></script>

这里请求了 Delicious Web 服务器上的数据,然后将其显示为无序列表。

尽量使用原生函数

例如:在一个数组中查找最大值时,我们可能需要遍历整个数组。

var numbers = [3, 342, 23, 22, 124];
var max = 0, i, j;

for (i = 0, j = numbers.length; i < j; i += 1) {
  if (numbers[i] > max) {
    max = numbers[i];
  }
}

alert(max); // => 342

可以不用循环,使用数组的 sort 来完成同样是任务。

var numbers = [3, 342, 23, 22, 124];

numbers.sort(function (a, b) {
  return b - a;
});

alert(numbers[0]); // => 342

我们也可以使用 Math.max()

var numbers = [3, 342, 23, 22, 124];

var max = Math.max.apply(null, numbers);

alert(max); // => 342

Math.max() 甚至可以用来检测浏览器支持哪个属性

var scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);

如果你想给元素添加 class,你可能会这样写

function addClass(element, class) {
  var currentClass = element.className;

  element.className = (currentClass === '') ? class : currentClass + ' ' + class;
}

也可以使用 split() 和 join() 来实现

function addClass(element, class) {
  var currentClasses = element.className.split(' ');

  currentClasses.push(class);

  element.className = currentClasses.join('');
}

这样做可以保证类与空格自动分离并且新加的类是显示在最后面的。

事件委托

事件是 JavaScript 非常重要的一部分。我们想给一个列表中的链接绑定点击事件,一般的做法是写一个循环,给每个链接对象绑定事件,HTML 代码如下:

<h2>Great Web resources<h2>
<ul id="resources">
  <li><a href="http://opera.com/wsc">Opera Web Standards Curriculuma</a></li>
  <li><a href="http://sitepoint.com">Sitepointa</a></li>
  <li><a href="http://alistapart.com">A List Aparta</a></li>
  <li><a href="http://yuiblog.com">YUI Bloga</a></li>
  <li><a href="http://blameitonthevoices.com">Blame it on the voicesa</a></li>
  <li><a href="http://oddlyspecific.com">Oddly specifica</a></li>
<ul>

脚本如下:

(function () {
  var resources = document.getElementById('resources');
  var links = resources.getElementByTagName('a');
  var len = links.length;

  for (var i = 0; i < len; i += 1) {
    links[i].addEventListener('click', handler, false);
  }

  function handler(e) {
    var x = e.target;

    alert(x);

    e.preventDefault();
  }
}());

更合理的写法是只给列表的父对象绑定事件,这样可行的原理在于事件是支持冒泡的,代码如下:

(function () {
  var resources = document.getElementById('resources');

  resources.addEventListener('click', handler, false);

  function handler(e) {
    var x = e.target;

    if (x.nodeName.toLocaleLowerCase() === 'a') {
      alert('Event delegation: ' + x);

      e.preventDefault();
    }
  }
}());

匿名函数

Javascript 最令人烦恼的事情是变量的范围没有定义。任何在函数外定义的变量、函数、数组和对象都是全局的,这意味着相同页中的其他脚本都可以进行调用,因而经常出现参数被覆盖的现象。解决方法就是将变量封装在一个匿名函数中,在定义完函数后立即调用。

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

function createMember() {}

function getMemberDetails() {}

该页中其他的脚本语句如果含有名为 status 的变量的话就会出现问题。如果将它们封装在名为 myApplication 的匿名函数中,就可以解决这个问题了。

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

  function createMember() {}

  function getMemberDetails() {}
}();

但是这样定义使得参数在函数外部不起作用,如果这正是所需要的,没有问题。另外可以省略定义的名字。

(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() {}
  }
}();

这样的用法被称为模块模式或单例模式。Douglas Crockford 多次提到过这个概念,Yahoo YUI 中经常使用它。为了使函数和变量可以被外部调用,需要改变定义的语法,这很令人烦恼。而且,如果要从一个方法中调用另一个方法,还必须在调用时加上 myApplication 前缀。因此,下面这种模式更好。

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

  function createMember() {}

  function getMemberDetails() {}

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

这种模式我们称作“揭示模块模式”。

配置

在 Javascript 程序中添加配置文件的几个要点

  • 在整个脚本文件中添加一个对象作为配置文件。
  • 在配置文件中加入使用该脚本程序可能需要改变的所有信息:
    • CSS 的 ID 和类的名称
    • 生成按钮的字符串
    • 数据:比如要展示的图片张数,地图的尺寸等
    • 地点、区域和语言设置
  • 将其作为全局属性返回该对象以便人们可以将其重载。大多数时候这一步放在编程的最后阶段。

其实,配置文件就是为了使代码更易于被其他开发人员使用和更改。

许可协议:署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
本文链接:https://tanglj.cn/2015/08/18/beginning-javascript/