[关闭]
@xudongh 2017-03-20T22:11:32.000000Z 字数 6431 阅读 1155

《JavaScript高级程序设计》部分内容复习

前端开发


第4章 变量、作用域和内存问题

4.1 基本类型和引用类型的值

两种数据类型

ECMAscript变量包含两种不同数据类型的值:

  1. 基本类型值:简单的数据段
    • 按值访问,直接操作变量中的值
    • 基本类型值不可添加属性
  2. 引用类型值:由多个值构成的对象
    • 不能直接操作对象的内存空间,实际上是在操作对象的引用而不是实际的对象
    • 可添加/改变/删除 引用类型值的属性和方法

5种基本数据类型

复制变量的值

基本类型:

  1. var num1 = 5;
  2. var num2 = num1;
  3. //num1中的5和num2中的5是完全独立的

引用类型:复制的是指针

  1. var obj1 = new Object();
  2. var obj2 = obj2;
  3. obj1.name = "Daniel";
  4. alert(obj2.name); //"Daniel"

传递参数

所有函数的参数都是按值传递的。
对于传递对象类型的参数:

  1. function setName(obj){
  2. obj.name = "Nicholas";
  3. obj = new Object();
  4. obj.name = "Greg";
  5. }
  6. var person = new Object();
  7. setName(person);
  8. alert(person.name); //"Nicholas"

如果person是按引用传递的,那么person就会自动被修改为指向其name属性值为"Greg"的新对象。但是,当接下来再访问person.name时,显示的值仍然是"Nicholas"。这说明即使在函数内部修改了参数的值,但原始的应用仍然保持不变。实际上,当在函数内部重写obj时,这个变量引用的就是一个局部对象了,而这个局部对象会在函数执行完毕后立即被销毁。

检测类型

typeof:确定一个变量是字符串、数值、布尔值、还是undefined。

instanceof:确定一个变量是什么类型的对象。

  1. console.log(person instanceof Object); //变量person是Object的实例吗?
  2. console.log(color instanceof Array); //变量color是Array的实例吗?

4.2 执行环境及作用域

某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁。

每个函数都有自己执行环境。

如果初始化变量时没有使用var声明,该变量会自动被添加到全局环境中。

解除引用:一旦数据不再有用,最好通过将其值设置为null来释放其引用。

  1. function Person(name){
  2. //...
  3. }
  4. var person1 = Person("Daniel");
  5. //手动解除Person的引用
  6. person1 = null;

第5章 引用类型

5.1 Object 类型

访问对象属性的两种方法:

5.2 Array 类型

数组的每一项都可以保存任何类型的数据。

所有对象都具有toLocaleString()toString()valueOf方法。

join()方法可以用时不同的分隔符来构建成字符串,join()方法只接收一个参数:

  1. var colors = ["red", "green", "blue"];
  2. cosole.log(colors.join("||")); //red||green||blue

栈方法、队列方法:

重排序方法:

操作方法:

注:concat()方法可由ES6扩展运算符来代替使用:

  1. //ES5
  2. [1,2].concat([2,3,4]) //[1,2,2,3,4]
  3. //ES6
  4. [1,2, ...[2,3,4]] //[1,2,2,3,4]

位置方法:

  1. var numbers = [1,2,3,4,5,5];
  2. console.log(numbers.indexOf(3)) //2

迭代方法:

5个迭代方法,每个方法都接收两个参数:要在每一项上运行的函数和(可选的)运行该函数的作用域对象——影响this的值。传入这些方法中的函数会接收三个参数:数组项的值、该项在数组中的位置和数组对象本身。

归并方法:
2个归并方法,迭代数组的所有项,然后构建一个最终返回的值。2个方法都接收两个参数:一个在每一项上调用的函数和(可选的)作为归并基础的初始值。传入方法的函数接收4个参数:前一个值、当前值、项的索引和数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上。

  1. var values =[1,2,3,4,5];
  2. var sum = values.reduce(function(prev , cur , index, array){
  3. return prev + cur;
  4. });
  5. console.log(sum); //15

5.3 Date类型

创建日期对象:

  1. var now = new Date();

如果不传入参数,日期对象会自动获得当前日期和时间。

分析代码运行时间:

  1. //取得开始时间
  2. var start = Date.now();
  3. //调用函数
  4. doSomething();
  5. //取得停止时间
  6. var stop = Date.now(),
  7. result = stop - start;

也可用console.timeconsole.timeEnd来实现这一过程:

  1. //开始
  2. console.time("string");
  3. //调用函数
  4. doSomething();
  5. //结束
  6. console.timeEnd("string");
  7. //控制台输入如下:
  8. string: 12.00ms

5.4 RegExp类型

ECMASCript通过RegExp来支持正则表达式。

5.5 Function类型

函数名是指向函数对象的指针,不会某个函数绑定。

JS函数没有重载。

函数内部属性

函数内部有两个特殊的对象:arguments和this。
arguments包含着传入函数中的所有参数。这个对象有一个callee属性,该属性是一个指针,指向拥有这个arguments对象的函数。

  1. //阶乘算法
  2. function factorial(num){
  3. if(num <= 1){
  4. return 1;
  5. } else {
  6. return num * factorial(num-1)
  7. }
  8. }
  9. //消除函数名自耦合
  10. function factorial(num){
  11. if(num <= 1){
  12. return 1;
  13. } else {
  14. return num * arguments.callee(num-1)
  15. }
  16. }

this引用的是函数据以执行的环境对象。

函数对象有一个caller属性,这个属性保存着调用当前函数的函数引用。
注意:该属性是函数对象的属性,而不是arguments的属性。

  1. function outer(){
  2. inner();
  3. }
  4. function inner(){
  5. console.log(inner.caller);
  6. //或者 console.log(arguments.callee.caller);
  7. }
  8. outer();
  9. //由于outer()调用了inner(),因此控制台输出为outer()函数的源代码

函数属性和方法

每个函数都包含两个属性:length和prototype。

函数的方法:apply()、call()和bind()。
- apply():接收两个参数,在其中运行函数的作用域和参数数组。
- call():接收多个参数,在其中运行函数的作用域和多个参数。
- bind():这个方法创建一个函数的实例,其this值会被绑定到传给bind()函数的值。

  1. window.color = "red";
  2. var o = { color: "blue" };
  3. function sayColor(){
  4. console.log(this.color);
  5. }
  6. var objectSayColor = sayColor.bind(o);
  7. objectSayColor(); //blue
  8. //等价于
  9. o.objectSayColor = sayColor;
  10. o.objectSayColor();

5.6 基本包装类型

为了便于操作基本类型值,ECMAScript还提供了2个特殊的引用类型:Boolean、Number和String。

  1. var s1 = "1234";
  2. console.log(s1.substring(2)); //34

引用类型和基本包装类型的区别:
用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中;
自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁,这以为这我们不能在运行时为基本类型值添加属性和方法。

注意:使用new调用基本包装类型的构造函数,与直接调用同名的转型函数是不一样的。

  1. var number = Number(10);
  2. console.log(typeof number); //number
  3. var obj = new Number(10);
  4. console.log(typeof obj); //object

Number类型

方法:
- toString():传递一个表示基数的参数,告诉它返回几进制数值的字符串形式。
- toFixed():按指定的小数位返回数值的字符串表示。
- toExponential():返回以指数表示法表示的数值的字符串形式,接受的参数是指定的小数位数。
- toPrecision():返回固定大小格式或者指数格式,具体看哪种格式最合适。接受的参数表示数值的所有数字的位数。

String类型

一些方法:

下面这两个方法用于搜索给定的子字符串,返回该子字符串的索引值。

字符串匹配方法:


第6章 面向对象的程序设计

6.1 理解对象

属性类型

ECMAScript有两种属性:数据属性和访问器属性。

1.数据属性

要修改属性默认的特性,必须使用ECMAScript 5的Object.defineProperty()方法。这个方法接收三个参数:

  1. var person = {};
  2. Object.defineProperty(person, "name", {
  3. writable: false,
  4. configurable: false,
  5. value: "Nicholas"
  6. })
  7. console.log(person.name); //"Nicholas"
  8. person.namre = "Greg";
  9. console.log(person.name); //"Nicholas"
  10. delete person.name;
  11. console.log(person.name); //"Nicholas"

在调用Object.defineProperty()方法时,如果不指定,configurable、enumerable和writable特性的默认值都是false。

2.访问器属性

在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值;
在写入访问器属性时,会调用setter函数,这个函数负责决定如果处理数据。

访问器属性有4个特性:

访问器不能直接定义,必须使用Object.defineProperty()来定义。

  1. var book = {
  2. _year: 2017, //_下划线是一种常用的记号,用于表示只能通过对象方法访问的属性。
  3. edition: 1
  4. };
  5. Object.defineProperty(book, "year", {
  6. get: function(){
  7. return this.year;
  8. },
  9. set: function(newValue) {
  10. if (newValue) {
  11. this._year = newValue;
  12. this.edition += newValue - 2017;
  13. }
  14. }
  15. });
  16. book.year = 2018;
  17. console.log(book.edition); //2

只指定getter函数意味着属性不能写,尝试写入属性会被忽略。
只指定setter函数意味着属性不能读。尝试读取属性会返回undefined。

定义多个属性

利用Object.defineProperties()方法可以通过描述符一次定义多个属性。这个方法就收两个对象参数:

读取属性的特性

使用Object.getOwnPropertyDescriptor()方法可以取得给定属性的描述符。

6.2 创建对象

工厂模式

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注