JavaScript语言精粹 笔记01 语法 对象

内容比较简单,只是从头梳理一下JS的知识

语法
空白
标识符
数字
字符串
语句

对象
对象字面量
检索
更新
引用
原型
反射
枚举
删除
减少全局变量污染

 

 语法

1 空白

空白可能表现为格式化字符或注释的形式。空白通常没有意义,但是偶尔必须用它来分割字符序列,否则它们就会被合并成一个单一的符号。例如:

var that = this;

var 和that之间的空格是不能去掉的,其他的空格都可以被移除。

JS提供两种注释:

  • /* */
  • //

建议使用//,因为/* */中要注释的内容可能包括字符 */ 而报错,例如:

/*

var rm_a=/a*/.match(s);

*/

 

2 标识符

标识符由一个字母开头,气候可选择性地加上一个或多个字母、数字或下划线。标识符不能用下面这些保留字:

abstract boolean break byte case catch char class const continue debugger default delete do double else enum export extends false final finally float for function goto if implements import in instanceof int interface long native new null package private protected public return short static super switch synchronized this throw throws transient true try typeof var volatile void while with

这些保留字和其他语言的保留字差不多

标识符也能以 $ 和 _ 符号开头(不过我们不推荐这么做)

标识符被用于语句、变量、参数、属性名、运算符和标识。

 

3 数字

JS只有一个单一的数字类型。它在内部表示为64位的浮点数。它没有分离出整数类型,所以1和1.0是相同的值。

如果一个数字字面量有指数部分,那么这个字面量是由e之前的部分乘以10的e之后部分的次方计算出来的。所以100和1e2是相同的数字。

负数可以用运算符-来构成。

值NaN是一个数值,它表示一个不能产生正常运算结果的的运算结果。NaN不等于任何值,包括它自己。

JS有一个对象Math,它包含一套用于数字的方法。例如Math.floor(number) 表示将一个数字装换成一个整数。

 

4 字符串

字符串可以包含在单引号或者双引号中,它可能包含0个或多个字符。\(反斜杠)是转义符。JS在创建的时候,Unicode是一个16为的字符集,所以JS中的所有字符都是16位的。

JS中没有字符类型。要表示一个字符,只需创建一个字符的字符串即可。

转义符允许那些正常情况下不被允许插入到字符串中的字符插入到字符串中,比如反斜杠、引号和控制符。\u 约定允许指定用数字表示字符码位。

"A"==="\u0041"

字符串有一个length属性。例如:"seven".length是5.

字符串是不可变的。一旦字符串被创建,就永远无法改变它。但通过+运算符去连接其他的字符串从而得到一个新的字符串是很容易的。两个包含相同字符且字符顺序也相同的字符串被认为是相同的字符串。所以:

'c'+'a'+'t'==='cat'

是true。

 

5 语句

if语句

if (条件)
{
只有当条件为 true 时执行的代码
}

 

下列值被当做假:

  • false
  • null
  • undefinde
  • 空字符串' '
  • 数字0
  • 数字NaN

其他所有的值都被当做真,包括true、字符串"false",以及所有的对象。

switch语句

switch(n)
{
case 1:
  执行代码块 1
  break;
case 2:
  执行代码块 2
  break;
default:
  n 与 case 1 和 case 2 不同时执行的代码
}

 

 

while语句

while (条件)
{
需要执行的代码
}

 

 

for语句

for (var i=0;i<cars.length;i++)
{
    document.write(cars[i] + "<br>");
}

 

 

do语句

do
{
需要执行的代码
}
while (条件);

 

 

try语句

try
{
//在这里运行代码
}
catch(err)
{
//在这里处理错误
}

 

 

throw语句

<script>
function myFunction()
{
try
  {
  var x=document.getElementById("demo").value;
  if(x=="")    throw "empty";
  if(isNaN(x)) throw "not a number";
  if(x>10)     throw "too high";
  if(x<5)      throw "too low";
  }
catch(err)
  {
  var y=document.getElementById("mess");
  y.innerHTML="Error: " + err + ".";
  }
}
</script>

<h1>My First JavaScript</h1>
<p>Please input a number between 5 and 10:</p>
<input id="demo" type="text">
<button type="button" onclick="myFunction()">Test Input</button>
<p id="mess"></p>

 

对象

JS的简单类型包括数字、字符串、布尔值(true和false) 和undefined值。其他所有的值都是对象。数字、字符串、布尔值“貌似”对象,因为它们有方法,但它们是不可变的。JS中的对象是可变的键控集合(keyed collections)。在JS中,数组是对象,函数是对象,正则表达式是对象,对象也是对象。

对象是属性的容器,其中每个属性都拥有名字和值。属性的名字可以是包括空字符串在内的任意字符串。属性的值可以是除undefined值之外的任何值。

JS中的对象是无类别的。它对新属性的名字和值没有约束。对象适合用于收集和整理数据。对象可以包含其他对象,它们可以容易的表示成树形或图形结构。

JS包括一个原型链特性,允许对象继承另一个对象的属性。正确的使用它能减少对象初始化的时间和内存消耗。

1 对象字面量

一个对象字面量就是包围在一对花括号中的零或多个“名/值”对。对象字面量可以出现在任何允许表达式出现的地方。

var empty_object = {};

var stooge = {
    "first-name": "Jerome",
    "last-name": "Howard"
};

 

属性名可以是包括空字符串在内的任何字符串。在对象字面量中,如果属性名是一个合法的JS标识符且不是保留字,并不强制要求用引号括住属性名。所以用引号括住"first-name"是必须的,但是否括住first_name则是可选的。逗号用来分隔多个“名/值”对。

属性的值可以从包括另一个对象字面量在内的任意表达式中获取。对象是可以嵌套的:

var flight = {
    airline: "Oceanic",
    number: 815,
    departure: {
        IATA: "SYD",
        time: "2004-09-22 14:55",
        city: "Sydney"
    },
    arrival: {
        IATA: "LAX",
        time: "2004-09-23 10:42",
        city: "Los Angeles"
    }
};

 

 

2 检索

要检索对象中包含的值,可以采用[]后缀中括住一个字符串表达式的方式。如果字符串表达式是一个常数,而且它是一个合法的JS标识符而非保留字,那么也可以用 . 表示法代替。优先考虑用 . 表示法,因为它更紧凑且可读性更好。

stooge["first-name"] // "Joe"
flight.departure.IATA // "SYD"

 

如果你尝试检索一个并不存在的成员元素的值,将返回一个undefined值。

stooge["middle-name"] // undefined
flight.status // undefined
stooge["FIRST-NAME"] // undefined

 

||运算符可用来填充默认值:

var middle = stooge["middle-name"] || "(none)";
var status = flight.status || "unknown";

 

尝试检索一个undefined值将会导致一个TypeError异常。这可以通过&&运算符来避免错误。

flight.equipment // undefined
flight.equipment.model // throw "TypeError"
flight.equipment && flight.equipment.model // undefined

 

 

3 更新

对象中的值可以通过赋值语句来更新。如果属性名已经存在于对象中,那么这个属性的值被替换。

stooge['first-name'] = 'Jerome';

如果对象之前并没有拥有那个属性名,那么该属性就被扩充到对象中。

stooge['middle-name'] = 'Lester';
stooge.nickname = 'Curly';
flight.equipment = {
model: 'Boeing 777'
};
flight.status = 'overdue';

 

 

4 引用

对象通过引用来传值,它们永远不会被拷贝:

var x = stooge;
x.nickname = 'Curly';
var nick = stooge.nickname;
//因为x和stooge是指向同一个对象的引用,所以nick为'Curly'
var a = {}, b = {}, c = {};
// a, b 和 c 每个都引用一个不同的空对象
a = b = c = {};
// a, b 和 c 都引用同一个空对象

 

 

5 原型

每个对象都连接到一个原型对象,并且它可以从中继承属性。所有通过对象字面量创建的对象都连接到Object.prototyoe 这个JS中标准的对象。

当创建一个新对象时,你可以选择某个对象作为它的原型。我们给Object增加一个create方法。这个create方法创建一个使用原型对象作为其原型的新对象。

if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        var F = function () {};
        F.prototype = o;
        return new F();
    };
}
var another_stooge = Object.create(stooge);

 

原型连接在更新时是不起作用的。当我们对某个对象做出改变时,不会触及到该对象的原型:

another_stooge['first-name'] = 'Harry';
another_stooge['middle-name'] = 'Moses';
another_stooge.nickname = 'Moe';

 

原型连接只有在检索值的时候才会被用到。如果我们尝试去获取对象的某个属性值,且该对象没有此属性名,那么JS会试着从原型对象中获取属性值。如果那个原型对象也没有该属性,那么再从它的原型中寻找,依次类推,直到该规程最后达到终点Object.prototype。如果想要的属性完全不存在于原型链中,那么结果就是undefined值。这个规程称为委托。

原型关系是一种动态关系。如果我们添加一个新的属性到原型中,该属性会立即对所有基于该原型创建的对象可见。

stooge.profession = 'actor';
another_stooge.profession // 'actor'

 

 

6 反射

检查对象并确定对象有什么属性是很容易的事情,只要试着去检索该属性并验证取得的值。

typeof操作符对确定属性的类型很有帮助:

typeof flight.number // 'number'
typeof flight.status // 'string'
typeof flight.arrival // 'object'
typeof flight.manifest // 'undefined'

 

请务必注意原型链中的任何属性也会产生一个值:

typeof flight.toString // 'function'
typeof flight.constructor // 'function'

 

有两种方法去处理这些不需要的属性。第一个时让你的程序检索并剔除函数值。一般来说做反射的目标是数据,因此你应该意识到一些值可能会是函数。

另一个方法是使用hasOwnProperty方法,如果对象拥有独有属性,它返回true。hasOwnProperty方法不会检查原型链。

flight.hasOwnProperty('number') // true
flight.hasOwnProperty('constructor') // false

 

 

7 枚举

for in 语句来遍历对象中的所有属性名。该枚举过程会列出所有的属性——包括函数和你不关心的原型中的属性——所以有必要过滤掉那些你不想要的值。最常用的过滤是hasOwnProperty方法,以及使用 typeof 来排除函数。

var name;
for (name in another_stooge) {
    if (typeof another_stooge[name] !== 'function') {
        document.writeln(name + ': ' + another_stooge[name]);
    }
}

 

属性名出现的顺序是不确定的,因此对任何可能出现的顺序要有所准备。如果想要确保属性以特定的属性出现,最好额办法是完全避免使用for in 语句,而是创建一个数组,在其中以正确的顺序包含属性名:

var i;
var properties = [
                'first-name',
                'middle-name',
                'last-name',
                'profession'
                ];
for (i = 0; i < properties.length; i += 1) {
    document.writeln(properties[i] + ': ' +
    another_stooge[properties[i]]);
}

 

通过for 而不是 for in,可以得到我们想要的属性,而不用担心可能会发掘出原型链中的属性,并且我们按正确的顺序得到它们的值。

 

8 删除

delete运算可以删除对象的属性。它会删除对象中确定的属性。它不会触及原型链中任何对象。

删除对象的属性可能会让原型链中的属性浮现出来:

another_stooge.nickname // 'Moe'
//删除another_stooge的nickname属性,从而暴露出原型的nickname属性
delete another_stooge.nickname;
another_stooge.nickname // 'Curly'

 

 

9 减少全局变量污染

JS可以随意地定义那些可以保存所有应用资源的全局变量。不幸的是,全局变量削弱了程序的灵活性,所有应该避免。

最小化使用全局变量的一个方法是在你的应用程序中只创建唯一一个全局变量:

var MYAPP={};

该变量此时变成了你的应用容器:

MYAPP.stooge = {
    "first-name": "Joe",
    "last-name": "Howard"
};
MYAPP.flight = {
    airline: "Oceanic",
    number: 815,
    departure: {
        IATA: "SYD",
        time: "2004-09-22 14:55",
        city: "Sydney"
    },
    arrival: {
        IATA: "LAX",
        time: "2004-09-23 10:42",
        city: "Los Angeles"
    }
};

 

只要将多个全局变量都整理到一个名称空间下,你将显著降低与其他应用程序、组件或类库之间产生糟糕的相互影响的可能性。

 

参考:《JavaScript语言精粹》Douglas Crockford著    赵泽欣 鄢学鹍 译

转载请注明出处:

作者:JesseLZJ
出处:http://jesselzj.cnblogs.com

posted @ 2015-09-05 23:37  JesseLZJ  阅读(459)  评论(0编辑  收藏  举报