第 5 章 引用类型
5.1 Object 类型
使用对象字面量定义函数时, 最后一个属性后面不要添加逗号. 如
- var person={
- name:"NIck",
- age:29
- };
5.2 Array 类型
Array.isArray(), 确定某个值是否是数组, 通常用于条件语句.
toString(),valueOf(),toLocaleString(), 返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串.
join(), 接收分隔符参数, 返回以这个分隔符分隔的数组字符串. 不传入值或传入 undefined, 默认以逗号分隔.
栈方法, push()末端推入, pop()弹出末项, 后进先出(LIFO).
队列方法, shift()移除第一项, push()末端推入, 先进先出(FIFO).
unshift()数组前端添加任意项, pop()弹出末项, 先进后出.
reverse(), 反转数组项的顺序.
sort(), 按升序排列数组项. 需传入比较函数 sort(compare). 如
- function compare(value1,value2){
- if(value1<value2){
- return -1;
- }else if(value1>value2){
- retrun 1;
- }else return 0;
- }
- var values=[0,1,5,10,15];
- values.sort(compare);
concat(), 基于当前数组所有项创建新数组. 接收 0 或多个数组作为参数.
slice(), 基于当前数组中一或多个项创建新数组. 接收 1 或 2 个参数, 要返回的项的起始和结束位置. 返回起始至结束位置之间的项但不包括结束位置的项.
splice(起始位置, 删除的项数, 要插入的项), 返回原数组删除项的数组. 可实现删除 Array.splice(0,1), 插入 Array.splice(1,0,"red","blue"), 替换 Array.splice(1,1,"red","blue")操作.
indexOf()从前往后查找, lastIndexOf()从后往前查找, 接收要查找的项和表示查找起点位置的索引.
every(), 对数组中每项运行给定函数, 每一项返回 true 则返回 true.
filter(), 对数组中每项运行给定函数, 返回 true 项组成的数组.
forEach(), 对数组中每项运行给定函数.
map(), 对数组中每项运行给定函数, 返回调用结果组成的数组.
some(), 对数组中每项运行给定函数, 如果有任一项返回 true 则返回 true.
reduce()从前往后, reduceRight()从后往前, 迭代数组中所有项, 返回最终值.
5.3 Date 类型
- Date()
- Date.parse()
- Date.UTC()
- Date.now()
- getTime()
- setTime()
5.4 RegExp 类型
var expression=/pattern/flags; 正则表达式字面量.
元字符,([{^$|)?*+.]}在正则表达式中具有特殊用途, 因此字符串中出现时必须使用 \ 转义.
var expression=new RegExp("[bc]at","i");RegExp 构造函数.
5.5 Function 类型
函数有以下三种定义:
1, 函数声明 function sum(num1,num2){// 函数体}
2, 函数表达式 var sum=function(num1,num2){// 函数体};
3,Function 构造函数 var sum=new Function("num1","num2","函数体");(不推荐)
解析器会率先读取函数声明, 并使其在执行任何代码前可用; 函数表达式必须等到解析器执行到它所在的代码才执行.
要访问函数的指针而不是执行函数, 必须去掉函数名后面的圆括号.
arguments 主要用途数保存函数参数, callee 属性是一个指针, 指向拥有这个 arguments 对象的函数. 函数中如要调用函数本身, 可以使用 arguments.callee()保证在更换函数名的情况下正常完成递归调用.
this 引用的是函数据以执行的环境对象.
函数名仅仅是一个包含指针的变量而已.
caller 属性保存着调用当前函数的函数引用, 如果是在全局作用域中调用当前函数, 值为 null. 如 function outer(){innder();}因为 outer()调用了 inner(), 所有 inner.caller 指向 outer(), 返回 outer()的源代码.
出于安全性考虑, arguments.caller 在严格模式下报错, 非严格模式下始终返回 undefined.
函数的 length 属性表示函数希望接收的命名参数的个数.
prototype 保存着引用类型所有实例方法.
apply()和 call()在特定的作用域中调用函数. apply()接收 this 和参数数组 (可使用 arguments).call() 接收 this 和逐个列出的参数数组. 它们能够扩充函数作用域.
bind()创建函数一个函数实例, 其 this 值会被绑定到传给 bind()函数的值.
5.6 基本包装类型
三种基本包装类型: Boolean,Number,String. 基本类型值可以被当做对象来访问. 操作基本类型值的语句一旦执行完毕, 就会立即销毁新创建的包装对象.
toFixed(), 按照指定的小数位返回数值的字符串表示.
toExponential(), 返回以指数表示法表示的数值的字符串形式.
toPrecision(), 表示某个数值最适合的格式.
chartAt(), 接收基于 0 的字符位置. 返回给定位置的那个单字符字符串.
chartCodeAt(), 接收基于 0 的字符位置. 返回给定位置的字符的字符编码.
substr(), 接收字符串开始的位置和返回字符串的个数. 传入负值时, 第一个参数加上字符串长度, 第二个参数转换为 0.
substring(), 接收字符串开始的位置和字符串最后一个字符后面的位置. 传入负值时, 会把第二个参数转换为 0, 将较小数作为开始位置, 较大数作为结束位置.
trim(), 创建一个字符串副本, 删除前置及后缀的所有空格.
toLowerCase(),toLocaleLowerCase(),toUpperCase(),toLocaleUpperCase()字符串大小写转换.
match(), 接收一个参数, 正则表达式或 RegExp 对象. 返回数组, 数组第一项是与整个模式匹配的字符串, 之后的每一项保存着与正则表达式中的捕获组匹配的字符串.
search(), 接收由字符串或 RegExp 对象指定的一个正则表达式, 返回字符串中第一个匹配项的索引, 没有找到匹配项返回 - 1.
replace(), 接收两个参数, 第一个参数是一个 RegExp 对象或字符串, 第二个参数是字符串或者函数. 如果第一个参数是字符串, 那么只会替换第一个子字符串; 要替换所有字符串, 则必须提供正则表达式, 且指定 g 标志. 返回替换后的字符串.
split(), 基于指定的分隔符将一个字符串分割成多个子字符串, 并保存为一个数组. 第二个参数指定数组大小.
localeCompare(), 比较两个字符串, 返回负数(小于),0(等于), 正数(大于).
fromCharCode(), 接收一或多个字符编码, 转换成字符串.
5.7 单体内置对象
encodeURI(), encodeURIComponent()对 URI 进行编码. 前者用于整个 URI, 不会对本身属于 URI 的字符进行编码, 如:/?# 等. 后者用于 URI 某一段, 会对发现的任何非标准字符进行编码.
decodeURI(), decodeURIComponent()对以上方法编码后的字符进行解码.
eval(), 接收要执行的 javascript 字符串. eval()的任何变量或函数只在执行到该位置时创建. 警惕使用 eval()创建执行用户输入数据的代码.
Math.min(),Math.max(), 确定一组数值中的最小最大值.
Math.floor(Math.random()* 可能值的总数 + 第一个可能值), 可以从某个范围获取某个值.
selectFrom(), 接收两个参数, 应该返回的最小值和最大值. 返回范围内的某个值.
第 6 章 面向对象的程序设计
6.1 理解对象
ES 中有两种属性: 数据属性, 访问器属性.
数据属性有 4 个描述其行为的特性:[[Configurable]]可配置, 能否通过 delete 删除属性, 重新定义属性, 修改为访问器属性, 默认 true;[[Enumerable]]可枚举, 能否通过 for-in 循环返回属性, 默认 true;[[Writable]]可写, 默认 true;[[Value]]属性值, 默认 undefined.
一旦把属性定义为不可配置的, 就不能再变回可配置的了.
Object.defineProperty()修改特性属性, 接收三个参数: 属性所在的对象, 属性的名字, 描述符对象(可多个).
在调用 Object.defineProperty()时, 如不指定, configurable,enumerable,writable 特性默认值 false.
Object.getOwnPropertyDescriptor()取得给定属性的描述符, 接收两个参数: 属性所在的对象, 要读取其描述符的属性., 默认 true;[[Enumerable]]可枚举, 能否通过 for-in 循环返回属性, 默认 true;[[get]]读取属性时调用的函数, 默认 undefined;[[set]]写入属性时调用的函数, 默认 undefined.
属性前加_, 表示只能通过对象方法访问.
只指定 getter 意味着属性不能写.
Object.defineProperties()通过描述符一次定义多个属性. 接收两个对象参数: 要添加和修改其属性的对象, 对象的属性与第一个对象中要添加或修改的属性一一对应.
Object.getOwnPropertyDescriptor()取得给定属性的描述符, 接收两个参数: 属性所在的对象, 要读取其描述符的属性名称.
6.2 创建对象
工厂模式, 用函数来封装以特定接口创建对象的细节, 如
- function createPerson(name,age,job){
- var o=new Object();
- o.name=name;
- o.sayName=function(){
- alter(this.name);
- };
- return o;
- }
构造函数模式, 创建自定义构造函数, 定义自定义对象类型的属性和方法, 构造函数应以大写字母开头, 非构造函数应以小写字母开头. 如
- function Person(name,age,job){
- this.name=name;
- this.sayName=function(){
- alert(this.name);
- };
- }
原型模式, prototype 就是通过调用构造函数创建的对象实例的原型对象, 可以让所有对象实例共享它所包含的属性和方法. 如
- function Person(){
- }
- Person.prototype.name="Nicholas";
- Person.prototype.sayName=function(){
- alert(this.name);
- };
更简单的原型语法
- function Person(){
- }
- Person.prototype={
- name:"Nicholas",
- sayName:function(){
- alert(this.name);
- }
- };
默认情况下, 所有原型对象都会自动获得一个 constructor(构造函数)属性, 这个属性包含一个指向 prototype 属性所在函数的指针.
isPrototypeOf(), 如果 [[prototype]] 指向调用 isPrototypeOf()方法的对象, 那么这个方法就返回 true.
Object.getPrototypeOf()返回 [[prototype]] 的值.
每当代码读取某个对象的某个属性时, 都会执行一次搜索, 目标是具有给定名字的属性. 搜索首先从对象实例本身开始. 如果在实例中找到了具有给定名字的属性, 则返回该属性的值; 如果没有找到, 则继续搜索指针指向的原型对象, 在原型对象中查找具有给定名字的属性. 如果在原型对象中找到了这个属性, 则返回该属性的值.
不能通过对象实例重写原型中的值, 当为对象实例添加一个属性时, 这个属性就会屏蔽原型对象中保存的同名属性.
delete 操作符可以完全删除实例属性.
hasOwnProperty()方法可以检测一个属性是存在于实例中还是原型中, 存在于对象实例中时返回 true.
单独使用 in 操作符会在通过对象能够访问给定属性时返回 true.
Object.keys()可以取得对象上所有可枚举的实例属性, 接收一个对象作为参数, 返回一个包含所有可枚举属性的字符串数组.
Object.getOwnPropertyNames()可以得到所有实例属性.
Object.defineProperty()重设构造函数 constructor 属性.
重写原型对象切断了现有原型与任何之前已经存在的对象实例之间的联系.
创建自定义类型最常见方式, 是组合使用构造函数模式与原型模式. 构造函数模式用于定义实例属性, 原型模式用于定义方法和共享的属性.
动态原型模式, 把所有信息都封装在构造函数中, 通过检查某个应该存在的方法是否有效, 来决定是否需要初始化原型.
寄生构造函数模式, 可以在特殊情况下用来为对象创建构造函数. 基本思想是创建一个函数, 作用仅为封装创建对象的代码, 然后再返回新创建的对象. 构造函数在不返回值的情况下, 默认返回新对象实例. 返回的对象与构造函数或者与构造函数的原型属性之间没有关系.
稳妥构造函数模式, 稳妥对象指的是没有公共属性, 而且其方法也不引用 this 的对象, 适合在安全环境 (禁用 this 和 new) 和防止数据被其他应用程序改动时使用.
6.3 继承
原型链作为继承的主要方法, 是利用原型让一个引用类型继承另一个引用类型的属性和方法. 如 SubType.prototype=new SuperType();
给原型添加方法的代码一定要放在替换原型的语句之后. 通过原型链实现继承时, 不能使用对象字面量创建原型方法.
借用构造函数, 解决原型中包含引用类型值所带来的问题, 通过在子类型构造函数的内部调用超类型构造函数. 可以在子类型构造函数中向超类型构造函数传递参数.
组合继承, 将原型链和借用构造函数的技术组合到一起. 使用原型链实现对原型属性和方法的继承, 通过借用构造函数来实现对实例属性的继承. 缺点是调用两次超类型构造函数: 一次在创建子类型原型的时候, 一次在子类型构造函数内部.
原型式继承, 借助原型可以基于已有的对象创建新对象, 不必因此创建自定义类型. 必须有一个对象可以作为另一个对象的基础.
寄生式继承, 创建一个仅用于封装继承过程的函数, 该函数在内部以某种方式来增强对象, 最后再像真地是它做了所有工作一样返回对象.
寄生组合式继承, 通过借用构造函数来继承属性, 通过原型链的混成形式来继承方法. 本质上是使用寄生式继承来继承超类型的原型, 再将结果指定给子类型的原型.
第 7 章 函数表达式
函数声明提升, 在执行代码前会先读取函数声明.
匿名函数的 name 属性是空字符串. 把函数当成值来使用的情况下, 都可以使用匿名函数.
函数表达式在使用前必须先赋值.
7.1 递归
递归函数, 一个函数通过名字调用自身. 调用自身时可以使用 arguments.callee 替代, 严格模式下可以使用命名函数表达式来达成同样效果.
7.2 闭包
闭包是指有权访问另一个函数作用域中的变量的函数. 创建闭包常见方式是在一个函数内部创建另一个函数.
将函数赋值给 null 可以解除匿名函数的使用.
作用域链的副作用, 闭包只能取得包含函数中任何变量的最后一个值. 可以通过创建另一个匿名函数强制让闭包的行为符合预期.
匿名函数的执行环境具有全局性, 因此 this 对象通常指向 window. 把外部作用域中的 this 对象保存在一个闭包能够访问的变量里, 就可以让闭包访问该对象.
如果闭包作用域链中保存 html 元素, 则该元素无法销毁. 闭包会引用包含函数的整个活动对象, 需要将保存着 html 的变量设置为 null 解除引用.
7.3 模仿块级作用域
匿名函数可以模仿块级作用域(私有作用域), 让变量只存在于块级作用域内. 如
- (function(){
- // 块级作用域
- })();
JavaScript 将 function 关键字当作一个函数声明的开始, 函数声明后面不能跟圆括号, 而函数表达式后面可以跟圆括号, 因此要将函数声明转换成函数表达式.
7.4 私有变量
任何在函数中定义的变量, 都可以认为是私有变量. 私有变量包括函数参数, 局部变量, 函数内部定义的其他函数.
特权方法, 如果在函数内部创建一个闭包, 闭包通过自己的作用域也可以访问这些变量.
利用私有和特权成员, 可以隐藏那些不应该被直接修改的数据.
利用原型定义特权方法, 访问到的属性是静态的, 由所有实例贡献的.
模块模式, 为单例创建私有变量和特权方法. 单例指的是只有一个实例的对象. 如果必须创建一个对象并以某些数据对其进行初始化, 同时还要公开一些能够访问这些私有数据的方法, 就可以使用模块模式.
在返回对象前加入对其增强的代码, 适用于单例必须是某种类型的实例, 还必须添加某些属性或方法的情况.
来源: http://www.jianshu.com/p/ffa095de8098