JavaScript高级程序设计
JavaScript高级程序设计
第3章 基本概念
3.6 语句
- 由于大量使用with语句会导致性能下降,同时也会给调试代码造成困难,因此在开发大型应用程序时,不建议使用with语句。
- switch语句中如果确实需要混合几种场景,不要忘了在代码中添加注释,说明你是有意省略了break关键字。
switch (i) {
case 25:
/* 合并两种场景说明 */
case 35:
// do something
break;
case 45:
// do something
break;
default:
alert('Other');
}
- switch语句在比较值的时候使用的是全等操作符,因此不会发生类型转换。
3.7 函数
- ECMAScript中的所有参数传递都是值,不可能通过引用传递参数。
- 不存在函数签名,真正的函数重载是不可能做到的。
- 如果在ECMAScript中定义了两个名字相同的函数,则该名字只属于后定义的函数。
第4章 变量、作用域和内存问题
4.1 基本类型和引用类型的值
- ECMAScript中所有的函数都是按值传递的。在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量(即命名参数)。在向参数传递引用类型的值时,会把这个值在内存中的地址复制一个给局部变量,因此这个变量的变化会反映在函数的外部。
- 执行环境是JavaScript中一个很重要的概念,它定义了变量或函数有权访问的其他数据,决定了他们各自的行为。其中全局执行环境是最外围的一个执行环境。
4.2 执行环境及作用域
- 某个执行环境中所有代码执行完成后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁。
- 每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境会被推入到一个环境栈中,执行完后,将其从栈中弹出,把控制权返回给之前的执行环境。
- 当代码在一个环境中执行时,会创建变量对象的一个作用域链。其用途是保证对执行环境有权访问的所有变量和函数的有序访问。
- 每个环境都能向上搜索作用域链,以查询变量和函数名;但任何环境都不能通过向下搜索作用域链而进入到另一个执行环境。
- 使用var声明的变量会自动被添加到最接近的环境中;如果初始化变量没有使用var声明,该变量会自动被添加到全局环境。
- 当在某个环境中为了读取或写入而引用一个标识符时,必须通过搜索来确定该标识符实际代表了什么。
4.3 垃圾收集
- JavaScript具备自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存。
- 收集原理:找出那些不再继续使用的变量,然后释放其占用的内存。为此,垃圾收集器会按照固定的时间间隔周期性的执行这一动作。
- JavaScript使用的是标记清除算法。收集器在运行的时候给存储在内存中的所有变量加上标记。
- 优化内存占用的最佳方式:为执行中的代码只保存必要的数据。一旦数据不使用,最好通过将其值设为null来释放其引用----这个做法叫做解除引用(dereferencing).
第5章 引用类型
引用类型的值(对象)是引用类型的一个实例。引用类型是一种数据结构,用于将数据和功能组织在一起。它也常被称为类,但这种称呼不妥当。尽管JavaScript从技术上讲是一门面向对象的语言,但它不具备传统面向对象语言所支持的类和接口等基本结构。引用类型有时候被称为对象定义,因为它们描述的是一类对象所具有的属性和方法。
5.1 Object类型
-
创建Object实例的方式有如下两种:
-
通过Object函数构造:
var person = new Object(); person.name = "Nicholas"; person.age = 29;
-
使用对象字面量表示法:
// 如下属性名可以是字符串,比如"name" var person = { name: "Nicholas", age: 29 };
-
2. **最佳实践**:函数**传参设计**中,对那些必须值使用命名参数,而使用对象字面量来封装多个可选参数。
3. **最佳实践**:除非必须使用变量来访问属性,否则我们建议使用点表示法。JS中属性名是可以包含非字母非数字的。
### 5.2 Array类型
1. ECMAScript数组的每一项可以保存任何类型的数据;其大小是可以动态调整的。
2. 初始化方式:
```javascript
var names = new Array();
var names = new Array(20);
var names = new Array("wangqian");
var names = new Array("wangqian", "wangjie");
var names = ["wangqian", "dongzifang"];
-
数组常用属性
// 数组长度 var names = ["wangqian", "dongzifang"]; // length属性不是只读的。可以通过设置该值,移除末尾元素or新增元素 console.log(names.length); // 2 names.length = 1; // 只保留一个元素 names.length = 3; // 新增了一个undefined元素
-
判断对象是不是数组:
if (value instanceof Array) { // todo } // ES5以后 if (Array.isArray(value)) { // todo }
-
栈方法:
push(); // 接受任意数量的参数,把它们逐个添加到数组末尾 pop(); // 从数组末尾移除最后一项,减少数组length值,然后返回移除的项。
-
队列方法:
push(); shift(); // 移除数组中的第一个项并返回该项。
-
重排序方法:
reverse(); sort(); sort(compareFunction);
-
其他方法
contact(); slice(); splice(); indexOf(); lastIndexOf(); every(); filter(); map(); forEach(); some(); reduce();reduceRight();
5.3 Date类型
不说废话,上代码:
let now = new Date(); //2019-09-22T15:24:16.339Z
now = Date.parse("2019-02-02 22:22:22"); // 1549117342000
now = new Date(Date.parse('2019-09-22')); // 2019-09-22T00:00:00.000Z
now = Date.UTC(2019, 0); // 1546300800000
now = new Date(Date.UTC(2019, 0)); // 2019-01-01T00:00:00.000Z
now = new Date(2019, 0); // 2018-12-31T16:00:00.000Z
now = Date.now(); // 1569167216891
now = Date.now().valueOf(); // 1569167516716
now = new Date().toDateString(); // Sun Sep 22 2019
now = new Date().toTimeString(); // 23:53:23 GMT+0800 (GMT+08:00)
now = new Date().toLocaleDateString(); // 2019-9-22
now = new Date().toLocaleTimeString(); // 23:54:11
now = new Date().toUTCString(); // Sun, 22 Sep 2019 15:54:34 GMT
5.4 RegExp类型
-
正则表达式元字符:( [ { \ ^ $ | } ] ) ? * + .
-
RegExp用法:
var parttern1 = /at/g; var parttern2 = /[bc]at/i; var parttern3 = /.at/gi; var parttern4 = new RegExp("[bc]at", "i");
-
ECMAScript5明确规定,使用正则表达式字面量必须像直接调用RegExp构造函数一样,每次都创建新的实例。
-
RegExp对象的主要方法是exec(),该方法是专门为捕获组设计的。有匹配则返回一个Array实例,没有则返回null。还有包含两个额外的属性:index和input。index匹配在字符串中的位置,而input表示应用正则表达式的字符串。
let text = "this has been a short summer"; let pattern = /(..)ort/g; let result = pattern.exec(text); console.log(result.index); // 16 console.log(result.input); // this has been a short summer console.log(result[0]); // short console.log(result[1]); // sh console.log(result[2]); // undefined
-
对于exec()而言,即使在模式中设置了全局标志(g),它每次也只会返回一个匹配项。
-
RegExp构造函数包含一些属性(在其他语言中被看成是静态属性)。这些属性域中的所有正则表达式,并且基于所执行的最近一次正则表达式操作而变化。包括:lastMatch等。
5.5 Function类型
函数是对象,函数名是指针
-
将函数名想象为指针,也有助于理解为什么ECMAScript中没有函数重载的概念。
-
函数声明与函数表达式区别:
// 如下输出20 console.log(sum1(10, 10)); function sum1(num1, num2) { return num1 + num2; } // 如下代码会抛错:ReferenceError: Cannot access 'sum' before initialization console.log(sum2(1, 2)); let sum2 = function (num1, num2) { return num1 + num2; };
-
ECMAScript中的函数名本身就是变量,所以函数也可以作为值来使用。
function createComparisonFunction(propertyName) { return function (object1, object2) { let value1 = object1[propertyName]; let value2 = object2[propertyName]; if (value1 < value2) { return -1; } else if (value1 > value2) { return 1; } else { return 0; } } }; let data = [{name: 'wangqian', age: 28}, {name: "wangqian2", age: 18}]; data.sort(createComparisonFunction("name")); console.log(data[0].name); data.sort(createComparisonFunction("age")); console.log(data[0].name);
-
函数内部属性:
-
arguments:其主要保存函数参数。它还包含一个叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。
function factorial(num) { if (num <= 1) { return 1; } return num * arguments.callee(num-1); }
-
this:其引用的是函数执行的环境对象----或者也可以说是this值(当在网页的全局作用域中调用函数时,this对象引用的就是window)。函数的名字仅仅是一个包含指针的变量而已。即使时在不同的环境中执行,全局函数or对象函数仍然是同一个函数。
-
转载:https://blog.csdn.net/weixin_38342703/article/details/101224271