js高级程序设计第二部分

js高级程序设计:函数、变量、作用域、引用类型

基本概念

函数

基本知识
  1. 语法
function functionName(arg0, arg1,...,argN) { 
 statements 
}
  1. 函数默认没有返回值,只有以通过return 语句后跟要返回的值来实现返回值,注意执行完 return 语句之后停止并立即退出。因此,函数体内位于 return 语句之后的任何代码都永远不会执行。
    后面的内容在首页不显示,请点击下方的展开全文或者
参数
  1. ECMAScript 函数不介意传递进来多少个参数,也不在乎传进来参数是什么数据类型,
    • 原因是 ECMAScript 中的参数在内部是用一个数组来表示的。函数接收到的始终都是这个数组,而不关心数组中包含哪些参数(如果有参数的话)
    • 在函数体内可以通过 arguments 对象来访问这个参数数组,从而获取传递给函数的每一个参数。例如
function sayHi() { 
 alert("Hello " + arguments[0] + "," + arguments[1]); 
}
没有重载

如果在 ECMAScript 中定义了两个名字相同的函数,则该名字只属于后定义的函数

变量、作用域、内存

基本类型和引用类型的值

  1. 基本信息
  • 基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。
  • 引用类型的值是保存在内存中的对象,js不允许直接操作对象的内存空间,所以操作对象实际上是在操作对象的引用。当复制保存着对象的某个变量时,操作的是对象的引用,但在为对象添加属性时,操作的是实际的对象
  1. 特点
  • 基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中;
  • 引用类型的值是对象,保存在堆内存中;包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针;
动态的属性

只能给引用类型值动态添加属性

复制变量值
  1. 基本类型:如果从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。这两个变量可以参与任何操作而不会相互影响
  2. 引用类型:当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中,但这个值的副本是一个针指向存储在堆中的一个对象指针,复制操作结束后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响另一个变量。
传递参数
  1. es中所有函数的参数都是按值传递的,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样
  • 在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量(即命名参数,或者用ECMAScript 的概念来说,就是 arguments 对象中的一个元素)
  • 在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部
/*示例1,参数是按值传递的,obj 按引用来访问同一个对象,当在函数内部为 obj 添加 name
属性后,函数外部的 person 也将有所反映*/
function setName(obj) {
 obj.name = "Nicholas"; 
} 
var person = new Object(); 
setName(person); 
alert(person.name); //"Nicholas"

/*示例2,参数是按值传递的,即使在函数内部修改了参数的值,但原始的引用仍然保持未变
实际上,当在函数内部重写 obj 时,这个变量引用的就是一个局部对象了。而这个局部对象会在函数执行完毕后立即被销毁。 */
function setName(obj) { 
 obj.name = "Nicholas"; 
 obj = new Object(); 
 obj.name = "Greg"; 
} 
var person = new Object(); 
setName(person); 
alert(person.name); //"Nicholas"
  1. 把 ECMAScript 函数的参数想象成局部变量。局部对象会在函数执行完毕后立即被销毁
检测类型
  1. 检测基本数据类型用typeof,如果变量的值是一个对象或 null,则 typeof 返回"object"
  2. 检测引用类型的值用instanceof,原理是根据它的原型链来识别
//语法
result = variable instanceof constructor
  • 检测一个引用类型值和 Object 构造函数时,instanceof始终会返回 true
  • 检测基本类型的值,则该操作符始终会返回 false,因为基本类型不是对象
  • 注意跨域无法使用,(要确认一下)

执行环境和作用域

  1. 执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。
  2. 执行环境有全局执行环境(也称为全局环境)和函数执行环境
  • 全局执行环境是最外围的一个执行环境,在 Web 浏览器中,全局执行环境被认为是 window 对象,因此所有全局变量和函数都是作为 window 对象的属性和方法创建的
  • 函数的局部环境不仅有权访问函数作用域中的变量,而且有权访问其包含(父)环境,乃至全局环境;
  • 全局环境只能访问在全局环境中定义的变量和函数,而不能直接访问局部环境中的任何数据;
  1. 某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁,全局执行环境直到应用程序退出——例如关闭网页或浏览器——时才会被销毁
  2. 每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。
  3. 当代码在一个环境中执行时,会创建变量对象的一个作用域链,它保证对执行环境有权访问的所有变量和函数的有序访问。
  • 内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数
  • 每个环境都可以向上搜索作用域链,以查询变量和函数名;但任何环境都不能通过向下搜索作用域链而进入另一个执行环境。
延长作用域链
  1. 方法:在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除。
  • try-catch 语句的 catch 块;创建一个新的变量对象,其中包含的是被抛出的错误对象的声明
  • with 语句。将指定的对象添加到作用域链中
没有块级作用域
  1. 声明变量,使用 var 声明的变量会自动被添加到最接近的环境中。
  • 在函数内部,最接近的环境就是函数的局部环境;
  • 在 with 语句中,最接近的环境是函数环境。
  • 如果初始化变量时没有使用 var 声明,该变量会自动被添加到全局环境。
  1. 查询标识符,搜索过程从作用域链的前端(当前执行环境)开始,向上逐级查询与给定名字匹配的标识符
  • 如果局部环境中存在着同名标识符,就不会使用位于父环境中的标识符

垃圾收集

  1. JavaScript 具有自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存。
  2. 原理:按照固定的时间间隔找出那些不再继续使用的变量,然后释放其占用的内存。
  3. 函数中局部变量的正常生命周期:只在函数执行的过程中存在
  4. 标识无用变量的策略:标记清除和引用计数
标记清除
  1. 运行机制:垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记,然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后,垃圾收集器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。
引用计数
  1. 运行机制:跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是 1。如果同一个值又被赋给另一个变量,则该值的引用次数加 1。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减 1。当这个值的引用次数变成 0 时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来。这样,当垃圾收集器下次再运行时,它就会释放那些引用次数为零的值所占用的内存
  2. 存在问题:循环引用,如果两个对象发生了循环引用,那么它们的引用次数永远不会是 0,如果被重复多次调用,就会导致大量内存得不到回收
/*举例:变量 myObject 有一个名为 element 的属性指向 element 对象;而变量 element 也有
一个属性名叫 someObject 回指 myObject。由于存在这个循环引用,即使将例子中的 DOM 从页面中
移除,它也永远不会被回收。*/
var element = document.getElementById("some_element"); 
var myObject = new Object(); 
myObject.element = element; 
element.someObject = myObject;

//解决方法:不使用它们的时候手工断开连接
myObject.element = null; 
element.someObject = null;
性能问题:

动态确定垃圾收集的时间间隔

管理内存
  1. 分配给 Web浏览器的可用内存数量通常要比分配给桌面应用程序的少,目的是防止运行 JavaScript 的网页耗尽全部系统内存而导致系统崩溃
  2. 优化内存占用的最佳方式,就是为执行中的代码只保存必要的数据。一旦数据不再有用,最好通过将其值设置为 null 来释放其引用——这个做法叫做解除引用
  • 解除引用适用于大多数全局变量和全局对象的属性,
  • 局部变量会在它们离开执行环境时自动被解除引用
  • 解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收

引用类型

object类型

创建实例的方式
  1. 使用 new 操作符后跟 Object 构造函数
var person = new Object(); 
person.name = "Nicholas"; 
person.age = 29;
  1. 使用对象字面量表示法,通过对象字面量定义对象时,不会调用 Object 构造函数
var person = { 
 name : "Nicholas", 
 
 
 age : 29 
};

//使用对象字面量语法时,如果留空其花括号,则可以定义只包含默认属性和方法的对象
var person = {}; //与 new Object()相同
  • 对象字面量也是向函数传递大量可选参数的首选方式
/*示例:这种传递参数的模式最适合需要向函数传入大量可选参数的情形*/
function displayInfo(args) { 
 var output = ""; 
 if (typeof args.name == "string"){ 
 output += "Name: " + args.name + "\n"; 
 } 
 if (typeof args.age == "number") { 
 output += "Age: " + args.age + "\n"; 
 } 
 alert(output); 
} 
displayInfo({ 
 name: "Nicholas", 
 age: 29 
}); 
displayInfo({ 
 name: "Greg" 
});
访问对象属性方法:点表示法和方括号表示法

1 使用方括号语法时,应该将要访问的属性以字符串的形式放在方括号中,优点是

  • 可以通过变量来访问属性
alert(person["name"]); //"Nicholas" 
alert(person.name); //"Nicholas"
  • 如果属性名中包含会导致语法错误的字符,或者属性名使用的是关键字或保留字,也可以使用方括号表示法
person["first name"] = "Nicholas";

array类型

基础
  1. 创建数组的基本方法
  • 使用 Array 构造函数
    • 可以给构造函数传递道数组要保存的项目数量
    • 可以向 Array 构造函数传递数组中应该包含的项
    • 给构造函数传递一个值,传递的是数值,则会按照该数值创建包含给定项数的数组;而如果传递的是其他类型的参数,则会创建包含那个值的只有一项的数组
    • 使用 Array 构造函数时也可以省略 new 操作符
var colors = new Array();
var colors = new Array(20);
var colors = new Array("red", "blue", "green");
  • 使用数组字面量表示法,数组字面量由一对包含数组项的方括号表示,多个数组项之间以逗号隔开,在使用数组字面量表示法时,也不会调用 Array 构造函数
var colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
var names = []; // 创建一个空数组
  1. 特点
  • 数组的每一项可以保存任何类型的数据
  • 数组的大小是可以动态调整的,即可以随着数据的添加自动增长以容纳新增数据
  1. 索引
  • 方括号中的索引表示要访问的值。如果索引小于数组中的项数,则返回对应项的值,索引超过了数组现有项数,数组就会自动增加长度
  • 索引数字基于 0 开始
  1. 数组的 length 属性,设置这个属性,可以从数组的末尾移除项或向数组中添加新项
检测数组
  1. 对于一个网页,或者一个全局作用域而言,使用 instanceof 操作符就可以判断
  2. 如果网页中包含多个框架或多个全局执行环境,需要使用了 Array.isArray()方法,这个方法的目的是最终确定某个值到底是不是数组,而不管它是在哪个全局执行环境中创建的
if (Array.isArray(value)){ 
 //对数组执行某些操作
}
转换方法
  1. 调用数组的 toString()方法会返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串
  2. 调用 valueOf()返回的还是数组
  3. 调用数组的 toLocaleString()方法时,它也会创建一个数组值的以逗号分隔的字符串
  4. 使用 join()方法,则可以使用不同的分隔符来构建上述三个方法返回的字符串
  • join()方法只接收一个参数,即用作分隔符的字符串,然后返回包含所有数组项的字符串。
var colors = ["red", "green", "blue"]; 
alert(colors.join("||")); //red||green||blue
  1. 如果数组中的某一项的值是 null 或者 undefined,那么该值在 join()、toLocaleString()、toString()和 valueOf()方法返回的结果中以空字符串表示。
栈方法
  1. 栈是一种 LIFO(Last-In-First-Out,后进先出)的数据结构,也就是最新添加的项最早被移除,而栈中项的插入(叫做推入)和移除(叫做弹出),只发生在一个位置——栈的顶部。类似喝水的杯子
  2. push()和 pop()方法
  • push()方法可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度
  • pop()方法则从数组末尾移除最后一项,减少数组的 length 值,然后返回移除的项
队列方法
  1. 队列数据结构的访问规则是 FIFO(First-In-First-Out,先进先出)。队列在列表的末端添加项,从列表的前端移除项。类似于一条单向的管道
  2. shift(),它能够移除数组中的第一个项并返回该项,同时将数组长度减 1。
  • 结合使用 shift()和 push()方法,可以像使用队列一样使用数组。
  1. unshift(),在数组前端添加任意个项并返回新数组的长度
  • 使用 unshift()和 pop()方法,可以从相反的方向来模拟队列,即在数组的前端添加项,从数组末端移除项
重排序方法
  1. reverse()和 sort()
  • reverse()方法会反转数组项的顺序
  • 默认情况下,sort()方法按升序排列数组项,特别地,sort()方法可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值的前面。
    • 比较函数接收两个参数,如果第一个参数应该位于第二个之前则返回一个负数,如果两个参数相等则返回 0,如果第一个参数应该位于第二个之后则返回一个正数
    • 对于数值类型或者其 valueOf()方法会返回数值类型的对象类型,可以使用一个更简单的比较函数。这个函数只要用第二个值减第一个值即可
function compare(value1, value2){ 
 return value2 - value1; 
}
操作方法
  1. concat()方法可以基于当前数组中的所有项创建一个新数组
  • 没有给 concat()方法传递参数的情况下,它只是复制当前数组并返回副本
  • 传递给 concat()方法的是一或多个数组,则该方法会将这些数组中的每一项都添加到结果数组中
  • 传递的值不是数组,这些值就会被简单地添加到结果数组的末尾
  1. slice(),基于当前数组中的一或多个项创建一个新数组,接受一或两个参数,即要返回项的起始和结束位置,含头不含尾
  • 只有一个参数的情况下,slice()方法返回从该参数指定位置开始到当前数组末尾的所有项
  • 有两个参数,该方法返回起始和结束位置之间的项,但不包括结束位置的项
  • slice()方法不会影响原始数组
  1. splice()的主要用途是向数组的中部插入项,返回一个数组,该数组中包含从原始数组中删除的项
  • 删除:可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数。例如,splice(0,2)会删除数组中的前两项。
  • 插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、0(要删除的项数)和要插入的项。如果要插入多个项,可以再传入第四、第五,以至任意多个项。例如,splice(2,0,“red”,“green”)会从当前数组的位置 2 开始插入字符串"red"和"green"。
  • 替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。例如,splice (2,1,“red”,“green”)会删除当前数组位置 2 的项,然后再从位置 2 开始插入字符串"red"和"green"。
位置方法
  1. indexOf():
  • 接收两个参数:要查找的项和(可选的)表示查找起点位置的索引
  • 法从数组的开头(位置 0)开始向后查找
  • 返回要查找的项在数组中的位置,没找到的情况下返回-1
  • 查找的项必须严格相等
  1. lastIndexOf()
  • 接收两个参数:要查找的项和(可选的)表示查找起点位置的索引
  • 从数组的末尾开始向前查找。
  • 返回要查找的项在数组中的位置,没找到的情况下返回-1
  • 查找的项必须严格相等
迭代方法

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

  1. every():对数组中的每一项运行给定函数,如果该函数对每一项都返回 true,则返回 true。
  2. filter():对数组中的每一项运行给定函数,返回该函数会返回 true 的项组成的数组。
  3. forEach():对数组中的每一项运行给定函数。这个方法没有返回值
  4. map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组
  5. some():对数组中的每一项运行给定函数,如果该函数对任一项返回 true,则返回 true。
var numbers = [1,2,3,4,5,4,3,2,1];
var everyResult = numbers.every(function(item, index, array){ 
 return (item > 2); 
}); 

alert(everyResult); //false 

var someResult = numbers.some(function(item, index, array){ 
 return (item > 2); 
}); 

alert(someResult); //true
归并方法

reduce()和 reduceRight(),这两个方法都会迭代数组的所有项,然后构建一个最终返回的值。这两个方法都接收两个参数:一个在每一项上调用的函数和(可选的)作为归并基础的初始值,函数接收 4 个参数:前一个值、当前值、项的索引和数组对象

  1. reduce()方法从数组的第一项开始,逐个遍历到最后
  2. reduceRight()则从数组的最后一项开始,向前遍历到第一项。
//使用 reduce()方法可以执行求数组中所有值之和的操作,比如:
var values = [1,2,3,4,5]; 
var sum = values.reduce(function(prev, cur, index, array){ 
 return prev + cur; 
}); 
alert(sum); //15

Date类型

  1. 创建日期对象
var now = new Date();
  • 调用 Date 构造函数而不传递参数的情况下,新创建的对象自动获得当前日期和时间
  • 创建特定的日期和时间的日期对象,必须传入表示该日期的毫秒数(即从 UTC 时间 1970 年 1 月 1 日午夜起至该日期止经过的毫秒数)。es提供了两个方法:Date.parse()和 Date.UTC()。
    • Date.parse()方法接收一个表示日期的字符串参数,然后尝试根据这个字符串返回相应日期的毫秒数,如果这个字符串不能表示日期,则返回NaN.直接将表示日期的字符串传递给 Date 构造函数,也会在后台调用 Date.parse()
    • Date.UTC()方法同样也返回表示日期的毫秒数,。Date.UTC()的参数分别是年份、基于 0 的月份(一月是 0,二月是 1,以此类推)、月中的哪一天(1 到 31)、小时数(0 到 23)、分钟、秒以及毫秒数,只有前两个参数是必须的
  1. ECMAScript 5 添加了 Data.now()方法,返回表示调用这个方法时的日期和时间的毫秒数,支持该方法的浏览器从ie9开始,兼容的方法是使用+操作符把 Data 对象转换成字符串
var start = Date.now(); 
//调用函数
doSomething(); 
//取得停止时间
var stop = Date.now(), 
 result = stop – start;
 
 //与上面的等价
 //取得开始时间
 var start = +new Date(); 
 //调用函数
 doSomething(); 
 //取得停止时间
 var stop = +new Date(), 
  result = stop - start;
继承的方法
  1. Date 类型的 toLocaleString()方法会按照与浏览器设置的地区相适应的格式返回日期和时间
  2. toString()方法则通常返回带有时区信息的日期和时间
  3. valueOf()方法,返回日期的毫秒表示
日期格式化方法
  1. toDateString()——以特定于实现的格式显示星期几、月、日和年;
  2. toTimeString()——以特定于实现的格式显示时、分、秒和时区;
  3. toLocaleDateString()——以特定于地区的格式显示星期几、月、日和年;
  4. toLocaleTimeString()——以特定于实现的格式显示时、分、秒;
  5. toUTCString()——以特定于实现的格式完整的 UTC 日期。
日期/时间组件方法

getXXXX(),setXXXX,直接取得和设置日期值中特定部分的方法,具体查表,列举几个

  1. getTime() 返回表示日期的毫秒数;与valueOf()方法返回的值相同
  2. setTime(毫秒) 以毫秒数设置日期,会改变整个日期
  3. getFullYear() 取得4位数的年份(如2007而非仅07)
  4. setFullYear(年) 设置日期的年份。传入的年份值必须是4位数字(如2007而非仅07)
  5. getMonth() 返回日期中的月份,其中0表示一月,11表示十二月
  6. setMonth(月) 设置日期的月份。传入的月份值必须大于0,超过11则增加年份

RegExp类型,用以支持正则

  1. 以字面量形式来定义的正则表达式
  • 语法
var expression = / pattern / flags ;
  • 模式(pattern)部分可以是任何简单或复杂的正则表达式
    • 模式中使用的所有元字符都必须转义。正则表达式中的元字符包括:( [ { \ ^ $ | ) ? * + .]}
/* 
* 匹配第一个" [bc]at",不区分大小写
*/ 
var pattern2 = /\[bc\]at/i;
  • 每个正则表达式都可带有一或多个标志(flags),用以标明正则表达式的行为,标志有:
    • g:表示全局(global)模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即停止;
    • i:表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写
    • m:表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中是否存在与模式匹配的项。
//示例
/* 
* 匹配字符串中所有"at"的实例
*/ 
var pattern1 = /at/g; 
/* 
* 匹配第一个"bat"或"cat",不区分大小写
*/ 
var pattern2 = /[bc]at/i; 
/* 
* 匹配所有以"at"结尾的 3 个字符的组合,不区分大小写
*/ 
var pattern3 = /.at/gi;
  1. 使用RegExp 构造函数,它接收两个参数:一个是要匹配的字符串模式,另一个是可选的标志字符串
//示例
var pattern2 = new RegExp("[bc]at", "i");
  • 由于 RegExp 构造函数的模式参数是字符串,所以在某些情况下要对字符进行双重转义,比如元字符和那些已经转义过的字符,例如/[bc]at/ 对应着"\[bc\]at"
RegExp实例属性,没什么用
  1. global:布尔值,表示是否设置了 g 标志。
  2. ignoreCase:布尔值,表示是否设置了 i 标志。
  3. lastIndex:整数,表示开始搜索下一个匹配项的字符位置,从 0 算起。
  4. multiline:布尔值,表示是否设置了 m 标志。
  5. source:正则表达式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回
RegExp实例方法
  1. exec(),该方法是专门为捕获组而设计
var text = "mom and dad and baby"; 
var pattern = /mom( and dad( and baby)?)?/gi; //包含两个捕获组。

var matches = pattern.exec(text); 
alert(matches.index); // 0 
alert(matches.input); // "mom and dad and baby"   
alert(matches[0]); // "mom and dad and baby"  与整个模式匹配的字符串
alert(matches[1]); // " and dad and baby"  与模式中的第一个捕获组匹配的字符串
alert(matches[2]); // " and baby"  与模式中的第二个捕获组匹配的字符串
  • exec()接受一个参数,即要应用模式的字符串,然后返回包含第一个匹配项信息的数组;或者在没有匹配项的情况下返回 null。
  • 返回的数组包含两个额外的属性:index 和 input。
    • index 表示匹配项在字符串中的位置,
    • input 表示应用正则表达式的字符串。
  • 在数组中,第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串
  • 不设置全局标志的情况下,在同一个字符串上多次调用 exec()将始终返回第一个匹配项的信息
  • 设置全局标志的情况下,每次调用 exec()则都会在字符串中继续查找新匹配项
  1. test(),接受一个字符串参数,在模式与该参数匹配的情况下返回true;否则,返回 fals
//示例
var text = "000-00-0000"; 
var pattern = /\d{3}-\d{2}-\d{4}/; 
if (pattern.test(text)){ 
 alert("The pattern was matched."); 
}
RegExp构造函数属性,看起来没什么用
模式的局限性,es不支持某些高级正则特性,例如向后查找,原子集,并集与交集类等

function类型

  1. 函数实际上是对象,每个函数都是 Function 类型的实例,与其他引用类型一样具有属性和方法,此函数名实际上也是一个指向函数对象的指针
  2. 函数的定义方式
  • 使用函数声明语法
function sum (num1, num2) { 
 return num1 + num2; 
}
  • 使用函数表达式
var sum = function(num1, num2){ 
 return num1 + num2; 
}; //注意末尾处的分号
  • 使用 Function 构造函数,但是不推荐使用,因为会引起二次解析影响性能
var sum = new Function("num1", "num2", "return num1 + num2");
函数没有重载,只有覆盖

声明了两个同名函数,而结果则是后面的函数覆盖了前面的函数

函数声明和函数表达式
  1. 解析器会率先读取函数声明,并使其在执行任何代码之前可用(可以访问)即函数声明提升;对于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行,所以如果在函数表达式之前就调用该函数会报错。
  2. 除了上面这一点,函数声明与函数表达式的语法其实是等价的
作为值的函数
  1. 函数可以作为值来使用,即不仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回
  2. 示例
function createComparisonFunction(propertyName) { 
 return function(object1, object2){ 
 var value1 = object1[propertyName]; 
 var value2 = object2[propertyName]; 
 if (value1 < value2){ 
 return -1; 
 } else if (value1 > value2){ 
 return 1; 
 } else { 
 return 0; 
 } 
 }; 
}

var data = [{name: "Zachary", age: 28}, {name: "Nicholas", age: 29}]; 
data.sort(createComparisonFunction("name")); 
alert(data[0].name); //Nicholas
函数内部属性

函数内部有两个特殊的对象:arguments 和 this。

  1. arguments 是一个类数组对象,包含着传入函数中的所有参数,它的主要用途是保存函数参数
  • 它有个叫callee 的属性,该属性是一个指针,指向拥有这个 arguments 对象的函数。
//一个经典的定义阶乘函数
function factorial(num){ 
 if (num <=1) { 
 return 1; 
 } else { 
 return num * factorial(num-1) 
 // return num * arguments.callee(num-1)    这样可以消除函数执行和函数名的耦合
 } 
}
  1. this引用的是函数据以执行的环境对象,谁调用它,它就指向谁
  • 当在网页的全局作用域中调用函数时,this 对象引用的就是 window
  1. 函数对象的属性:callee。这个属性中保存着调用当前函数的函数的引用,如果是在全局作用域中调用当前函数,它的值为 null
函数属性和方法
  1. length 属性表示函数希望接收的命名参数的个数
  2. prototype 属性,prototype 是保存引用类型所有实例方法的真正所在,诸如toString()和 valueOf()等方法实际上都保存在 prototype 名下,prototype 属性是不可枚举的
  3. apply()方法用途是在特定的作用域中调用函数,接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组。其中,第二个参数可以是 Array 的实例,也可以是arguments 对象
  4. call()方法用途是在特定的作用域中调用函数,接收两个参数::第一个参数是 this 值没有变化,第二个参数必须逐个列举出来
  5. apply()和 call()真正的用处是能够扩充函数作用域,并且函数对象不需要与方法有任何耦合关系
window.color = "red"; 
var o = { color: "blue" }; 
function sayColor(){ 
 alert(this.color); 
} 
sayColor(); //red 
sayColor.call(this); //red 
sayColor.call(window); //red 
sayColor.call(o); //blue
  1. bind()方法会创建一个函数的实例,其 this 值会被绑定到传给 bind()函数的值

基本包装类型:Boolean、Number 和String

  1. 每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据
  2. 引用类型与基本包装类型的主要区别就是对象的生存期。
  • 使用 new 操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中
  • 自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁。不能在运行时为基本类型值添加属性和方法
  1. Object 构造函数可以根据传入值的类型返回相应基本包装类型的实例。
  2. 使用 new 调用基本包装类型的构造函数,与直接调用同名的转型函数是不一样的。当使用typeof测试时,前者返回一个object,后者是对应的基本数据类型
Boolean类型,不建议使用Boolean对象
  1. 创建Boolean 对象,可以调用 Boolean构造函数并传入 true 或 false 值。
var booleanObject = new Boolean(true);
  1. Boolean 类型的实例重写了valueOf()方法,返回基本类型值true 或false;重写了toString()方法,返回字符串"true"和"false"。
  2. 存在问题:布尔表达式中的所有对象都会被转换为 true, Boolean 类型的实例在布尔表达式中也永远代表的是 true
  3. 基本类型与引用类型的布尔值的两个区别
  • typeof 操作符对基本类型返回"boolean",而对引用类型返回"object"
  • 使用 instanceof操作符测试 Boolean 对象会返回 true,而测试基本类型的布尔值则返回 false。
Number类型,不建议直接实例化 Number 类型
  1. 创建 Number 对象,可以在调用 Number 构造函数时向其中传递相应的数值
var numberObject = new Number(10);
  1. Number 类型也重写了 valueOf()、toLocaleString()和 toString()方法。
  • 重写后的 valueOf()方法返回对象表示的基本类型的数值,另外两个方法则返回字符串形式的数值
  • 可以为 toString()方法传递一个表示基数的参数,告诉它返回几进制数值的字符串形式
  1. Number 类型还提供了用于将数值格式化为字符串的方法。
  • toFixed()方法会按照指定的小数位返回数值的字符串表示,接收一个参数指定输出结果中的小数位数,如果数值本身包含的小数位比指定的还多,那么接近指定的最大小数位的值就会舍入,适合处理货币值
  • toExponential(),该方法返回以指数表示法(也称 e 表示法)表示的数值的字符串形式。接收一个参数指定输出结果中的小数位数
  • toPrecision()方法可能会返回固定大小(fixed)格式,也可能返回指数(exponential)格式,接收一个参数,即表示数值的所有数字的位数(不包括指数部分),toPrecision()会根据要处理的数值决定到底是调用 toFixed()还是调用 toExponential()。
String类型
  1. 使用 String 构造函数来创建对象。
var stringObject = new String("hello world");
  1. length 属性,表示字符串中包含多个字符
  2. 字符方法charAt()和 charCodeAt()用于访问字符串中特定字符,都接收一个参数,即基于 0 的字符位置
  • charAt()方法以单字符字符串的形式返回给定位置的那个字符
  • charCodeAt()以字符编码的形式返回给定位置的那个字符
  1. 字符串操作方法
  • concat(),用于将一或多个字符串拼接起来,返回拼接得到的新字符串,实践中使用更多的还是加号操作符(+)
  • 基于子字符串创建新字符串的方法slice()、substr()和 substring()。都返回被操作字符串的一个子字符串,而且也都接受一或两个参数
    • 第一个参数指定子字符串的开始位置,第二个参数(在指定的情况下)表示子字符串到哪里结束
    • 它们只是返回一个基本类型的字符串值,对原始字符串没有任何影响
    • 参数是负值
      • slice()方法会将传入的负值与字符串的长度相加
      • substr()方法将负的第一个参数加上字符串的长度,而将负的第二个参数转换为 0
      • substring()方法会把所有负值参数都转换为 0
  1. 字符串位置方法
  • 从字符串中查找子字符串的方法:indexOf()和 lastIndexOf(),返回子字符串的位置(如果没有找到该子字符串,则返回-1)。
    • indexOf()方法从字符串的开头向后搜索子字符串,
    • lastIndexOf()方法是从字符串的末尾向前搜索子字符串
  • 这两个方法都可以接收可选的第二个参数,表示从字符串中的哪个位置开始搜索
  1. trim()方法
  • 这个方法会创建一个字符串的副本,删除前置及后缀的所有空格,然后返回结果
  1. 字符串大小写转换方法
  • 涉及字符串大小写转换的方法有 4 个:toLowerCase()、toLocaleLowerCase()、toUpperCase()和 toLocaleUpperCase()。前两个通用,后两个是针对特定地区的实现
  1. 字符串的模式匹配方法
  • match(),在字符串上调用这个方法,本质上与调用 RegExp 的 exec()方法相同,只接受一个参数,要么是一个正则表达式,要么是一个 RegExp 对象
  • search(),它的参数与 match()方法的参数相同,search()方法返回字符串中第一个匹配项的索引;如果没有找到匹配项,则返回-1,而且,search()方法始终是从字符串开头向后查找模式
  • replace()方法,它接受两个参数:第一个参数可以是一个 RegExp 对象或者一个字符串(这个字符串不会被转换成正则表达式),第二个参数可以是一个字符串或者一个函数。如果第一个参数是字符串,那么只会替换第一个子字符串。要想替换所有子字符串,唯一的办法就是提供一个正则表达式,而且要指定全局(g)标志
var text = "cat, bat, sat, fat"; 
var result = text.replace("at", "ond"); 
alert(result); //"cond, bat, sat, fat" 

result = text.replace(/at/g, "ond"); 
alert(result); //"cond, bond, sond, fond"
  • split(),这个方法可以基于指定的分隔符将一个字符串分割成多个子字符串,并将结果放在一个数组中,分隔符可以是字符串,也可以是一个 RegExp 对象.split()方法可以接受可选的第二个参数,用于指定数组的大小,以便确保返回的数组不会超过既定大小
  1. localeCompare()方法,比较两个字符串,并返回下列值中的一个:
  • 如果字符串在字母表中应该排在字符串参数之前,则返回一个负数(大多数情况下是-1,具体的值要视实现而定);
  • 如果字符串等于字符串参数,则返回 0
  • 如果字符串在字母表中应该排在字符串参数之后,则返回一个正数(大多数情况下是 1,具体的值同样要视实现而定)
  1. fromCharCode()方法,是静态方法,是接收一或多个字符编码,然后将它们转换成一个字符串

单体内置对象

Global对象
  1. 不属于任何其他对象的属性和方法,最终都是它的属性和方法
  2. 事实上,没有全局变量或全局函数;所有在全局作用域中定义的属性和函数,都是 Global 对象的属性,诸如 isNaN()、isFinite()、parseInt()以及 parseFloat()
  3. Global 对象的其他方法:
  • URI 编码方法,Global 对象的 encodeURI()和 encodeURIComponent()方法可以对 URI(Uniform Resource Identifiers,通用资源标识符)进行编码,以便发送给浏览器。
  • eval()方法,超强大的方法,它只接受一个参数,即要执行的 ECMAScript(或 JavaScript)字符串
    • 当解析器发现代码中调用 eval()方法时,它会将传入的参数当作实际的 ECMAScript 语句来解析,然后把执行结果插入到原位置。
    • 通过 eval()执行的代码被认为是包含该次调用的执行环境的一部分,因此被执行的代码具有与该执行环境相同的作用域链。这意味着通过 eval()执行的代码可以引用在包含环境中定义的变量
    • eval()中创建的任何变量或函数都不会被提升,因为在解析代码的时候,它们被包含在一个字符串中;它们只在 eval()执行的时候创建。
    • 它的危险,可能会有恶意用户输入威胁你的站点或应用程序安全的代码(即所谓的代码注入)
  1. Global 对象的属性
  • 特殊的值undefined、NaN 以及 Infinity 都是 Global 对象的属性
  • 所有原生引用类型的构造函数,像Object 和 Function,也都是 Global 对象的属性
  1. window 对象
  • 在全局作用域中声明的所有变量和函数,就都成为了 window对象的属性
Math对象
  1. Math 对象的属性,一般为一些特殊值,例如π的值,10的自然对数等等
  2. min()和 max()方法,用于确定一组数值中的最小值和最大值,可以接收任意多个数值参数
  3. 舍入方法,Math.ceil()、Math.floor()和 Math.round()。
  • Math.ceil()执行向上舍入,即它总是将数值向上舍入为最接近的整数;
  • Math.floor()执行向下舍入,即它总是将数值向下舍入为最接近的整数;
  • Math.round()执行标准舍入,即它总是将数值四舍五入为最接近的整数
  1. random()方法,返回大于等于 0 小于 1 的一个随机数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值