JavaScrip基本语法

i 先给i自加1,再计算表达式的值。
i先计算表达式的值,再给i自加1。

需要注意的是,每个case代码块内部的break语句不能少,否则会接下去执行下一个case代码块,而不是跳出switch结构。

JavaScript 有三种方法,可以确定一个值到底是什么类型:

  • typeof运算符
  • instanceof运算符
  • Object.prototype.toString方法

区别是这样的:null是一个表示“空”的对象,转为数值时为0;undefined是一个表示”此处无定义”的原始值,转为数值时为NaN。

转换规则是除了下面六个值被转为false,其他值都视为true。

  • undefined
  • null
  • false
  • 0
  • NaN
  • “”或’’(空字符串)

注意,空数组([])和空对象({})对应的布尔值,都是true。

NaN是 JavaScript 的特殊值,表示“非数字”(Not a Number),主要出现在将字符串解析成数字出错的场合。0除以0也会得到NaN。需要注意的是,NaN不是独立的数据类型,而是一个特殊数值,它的数据类型依然属于Number,使用typeof运算符可以看得很清楚。

Infinity表示“无穷”,用来表示两种场景。一种是一个正的数值太大,或一个负的数值太小,无法表示;另一种是非0数值除以0,得到Infinity。Infinity有正负之分,Infinity表示正的无穷,-Infinity表示负的无穷。

字符串

由于 HTML 语言的属性值使用双引号,所以很多项目约定 JavaScript 语言的字符串只使用单引号,本教程遵守这个约定。

如果长字符串必须分成多行,可以在每一行的尾部使用反斜杠。注意,反斜杠的后面必须是换行符,而不能有其他字符(比如空格),否则会报错。

反斜杠还有三种特殊用法。\HHH 反斜杠后面紧跟三个八进制数(000到377),代表一个字符;\xHH \x后面紧跟两个十六进制数(00到FF),代表一个字符;\uXXXX \u后面紧跟四个十六进制数(0000到FFFF),代表一个字符。

字符串可以被视为字符数组,因此可以使用数组的方括号运算符,用来返回某个位置的字符(位置编号从0开始)。

但是,字符串与数组的相似性仅此而已。实际上,无法改变字符串之中的单个字符。字符串内部的单个字符无法改变和增删,这些操作会默默地失败。

对象

对象就是一组“键值对”(key-value)的集合,是一种无序的复合数据集合。

  1. var obj = {
  2. foo: 'Hello',
  3. bar: 'World'
  4. };

对象的所有键名都是字符串(ES6 又引入了 Symbol 值也可以作为键名),所以加不加引号都可以。对象的属性之间用逗号分隔,最后一个属性后面可以加逗号(trailing comma),也可以不加。

如果要解释为对象,最好在大括号前加上圆括号。因为圆括号的里面,只能是表达式,所以确保大括号只能解释为对象。

with它的作用是操作同一个对象的多个属性时,提供一些书写的方便。

  1. with (对象) {
  2. 语句;
  3. }
  4. / 例一
  5. var obj = {
  6. p1: 1,
  7. p2: 2,
  8. };
  9. with (obj) {
  10. p1 = 4;
  11. p2 = 5;
  12. }
  13. // 等同于
  14. obj.p1 = 4;
  15. obj.p2 = 5;
  16. // 例二
  17. with (document.links[0]){
  18. console.log(href);
  19. console.log(title);
  20. console.log(style);
  21. }
  22. // 等同于
  23. console.log(document.links[0].href);
  24. console.log(document.links[0].title);
  25. console.log(document.links[0].style);

函数

JavaScript 有三种声明函数的方法:

  1. function 命令
  2. 函数表达式
  1. var print = function(s) {
  2. console.log(s);
  3. };
  4. //这种写法的用处有两个,一是可以在函数体内部调用自身,二是方便除错
  5. var f = function f() {};
  1. Function 构造函数
  1. var add = new Function(
  2. 'x',
  3. 'y',
  4. 'return x + y'
  5. );
  6. // 等同于
  7. function add(x, y) {
  8. return x + y;
  9. }

如果只有一个参数,该参数就是函数体。

如果同一个函数被多次声明,后面的声明就会覆盖前面的声明。

JavaScript 引擎将函数名视同变量名,所以采用function命令声明函数时,整个函数会像变量声明一样,被提升到代码头部。但是,如果采用赋值语句定义函数,JavaScript 就会报错。

函数的属性和方法

函数的name属性返回函数的名字。

函数的length属性返回函数预期传入的参数个数,即函数定义之中的参数个数。

函数的toString方法返回一个字符串,内容是函数的源码。

参数的省略

运行时无论提供多少个参数(或者不提供参数),JavaScript 都不会报错。省略的参数的值就变为undefined。需要注意的是,函数的length属性与实际传入的参数个数无关,只反映函数预期传入的参数个数。

函数参数如果是原始类型的值(数值、字符串、布尔值),传递方式是传值传递(passes by value)。这意味着,在函数体内修改参数值,不会影响到函数外部。

但是,如果函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递(pass by reference)。也就是说,传入函数的原始值的地址,因此在函数内部修改参数,将会影响到原始值。

如果有同名的参数,则取最后出现的那个值。

arguments 对象

由于 JavaScript 允许函数有不定数目的参数,所以需要一种机制,可以在函数体内部读取所有参数。这就是arguments对象的由来。

arguments对象包含了函数运行时的所有参数,arguments[0]就是第一个参数,arguments[1]就是第二个参数,以此类推。这个对象只有在函数体内部,才可以使用。

闭包

如果出于种种原因,需要得到函数内的局部变量。正常情况下,这是办不到的,只有通过变通方法才能实现。那就是在函数的内部,再定义一个函数。

  1. function f1() {
  2. var n = 999;
  3. function f2() {
  4. console.log(n);
  5. }
  6. return f2;
  7. }
  8. var result = f1();
  9. result(); // 999

闭包就是函数f2,即能够读取其他函数内部变量的函数。由于在 JavaScript 语言中,只有函数内部的子函数才能读取内部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。闭包最大的特点,就是它可以“记住”诞生的环境,比如f2记住了它诞生的环境f1,所以从f2可以得到f1的内部变量。在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

闭包的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在。

闭包的另一个用处,是封装对象的私有属性和私有方法。

立即调用的函数表达式(IIFE)

  1. (function(){ /* code */ }());
  2. // 或者
  3. (function(){ /* code */ })();

上面两种写法都是以圆括号开头,引擎就会认为后面跟的是一个表示式,而不是函数定义语句,所以就避免了错误。这就叫做“立即调用的函数表达式”(Immediately-Invoked Function Expression),简称 IIFE。

  1. //简单说,它们的区别是相等运算符(==)比较两个值是否相等
  2. //严格相等运算符(===)比较它们是否为“同一个值”。
  3. //如果两个值不是同一类型,严格相等运算符(===)直接返回false
  4. //而相等运算符(==)会将它们转换成同一个类型,再用严格相等运算符进行比较。

This

但不管是什么场合,this都有一个共同点:它总是返回一个对象。简单说,this就是属性或方法“当前”所在的对象。

由于函数可以在不同的运行环境执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境(context)。所以,this就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。

  1. var f = function () {
  2. console.log(this.x);
  3. }
  4. var x = 1;
  5. var obj = {
  6. f: f,
  7. x: 2,
  8. };
  9. // 单独执行
  10. f() // 1
  11. // obj 环境执行
  12. obj.f() // 2