JavaScript知识集锦
ECMAScript 5.1目前已经受到现代浏览器的广泛支持,本章内容介绍其新特性。
在脚本文件或者函数体的第一行添加 'use strict'; 可以切换到严格模式。在此模式下JavaScript变得更加严谨、禁用某些特效、执行更多的检查、抛出更多的异常。严格模式造成的改变包括:
禁止全局变量的隐式声明 在正常模式下,不使用var声明的变量,自动作为全局变量。在严格模式下,所有变量必须通过var声明,否则报错 |
||||||
限制动态绑定上下文对象的能力 动态绑定允许在运行时确定上下文对象(函数、变量所属的对象),启用严格模式时:
|
||||||
禁止函数体中this指向全局对象
这样,调用构造函数时忘记使用new操作符,不会导致this意外的指向Global对象 |
||||||
禁止删除属性 默认的,在严格模式下你不能删除对象的属性,例如 delete obj.prop 会报错。除非声明目标属性的 configurable: true ,例如:
|
||||||
禁止定义重名的属性 在正常模式下,定义重名的属性会导致最后一个覆盖前面的定义,严格模式下则报错 |
||||||
禁止定义重名的形参 在正常模式下,两个形参名字一样是允许的,可以通过arguments数组访问,严格模式下则报错 |
||||||
禁止0开头的八进制表示法 |
||||||
更多的错误信息 正常模式下,某些失败的操作仅仅被简单的忽略,在严格模式下则会导致报错。例如:
|
||||||
限制arguments对象
|
||||||
函数声明位置限制 严格模式下,函数要么声明在全局作用域,要么声明在函数作用域的最外层:
|
||||||
更多的保留字 包括:implements, interface, let, package, private, protected, public, static, yield。这些保留字不得用于变量名 注:即使在正常模式下,class, enum, export, extends, import, super也是ECMAscript 5的保留字 |
这种新语法允许你为某个属性定义getter/setter,这样取值、赋值时实际上会调用这些Getter/Setter,而不是直接操控属性字段:
1 2 3 4 5 6 7 8 9 10 11 |
var person = { get name() { return this._name; }, set name( name ) { console.log( 'Changing name to ' + name ); // 不能用this.name,会导致无限递归 this._name = name; } } person.name = 'Alex'; // 打印 Changing name to Alex |
1 2 |
var obj = { new: null } obj.new = 1; |
1 2 |
var obj = { new: null, } var array = [,] |
1 2 3 4 5 |
var LINES = '1\ 2345\ 6789\ '; console.log( LINES.length ); // 9 |
1 2 |
var str = '12345'; console.log( str[ 1 ] ); |
JavaScript标准库的完整内容可以参考MDN。
注意依赖于Object类上新定义的一系列静态方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
/* 读写原型对象 */ // 创建一个新的对象。第一个参数用于指定其原型对象;第二个参数用于指定属性名到描述符的映射 obj = Object.create( proto, props ); // 获取一个对象的原型对象 proto = Object.getPrototypeOf( obj ); /* 通过属性描述符来操控属性 */ obj = Object.create( proto, props ); //创建新对象 // 为obj定义名为prop的属性,使用描述符desc Object.defineProperty( obj, prop, desc ); //示例 Object.defineProperty({},'name',{ value:'anonymous', // 默认值 writable: false, // 是否可以写入属性值 configurable:false, // 是否允许后续配置,如果否,则禁止修改writable、configurable、enumerable特性,禁止删除属性 enumerable:true , // 是否允许在for .. in循环中枚举出此属性 get:function(){} , // 读访问器 set:function(){} , // 写访问器 }); // 为obj定义多个属性 Object.defineProperties( obj, props ); // 得到obj对象的name属性的描述符 desc = Object.getOwnPropertyDescriptor( obj, 'name' ); /* 属性迭代 */ // 返回所有可枚举自身属性(不包括继承自原型链的)组成的数组,属性名排序与for..in循环一致 array = Object.keys( obj ); // 与上面类似,但是包括不可枚举属性 Object.getOwnPropertyNames(); /* 对象保护 */ // 禁止添加新属性 Object.preventExtensions( obj ); // 判断是否允许扩展 Object.isExtensible( obj ); // 密封一个对象,此后该对象不支持添加、删除属性,也不能对已有属性进行配置 obj = Object.seal( obj ); // 判断obj是否是密封对象 Object.isSealed( obj ); // 冻结一个对象,在密封的基础上,禁止修改属性值 Object.freeze( obj ); // 判断obj是否是冻结对象 Object.isFrozen( obj ); |
新添加一个 String.prototype.trim() 方法,可以删除字符串开头、结尾的空白字符。
新增加 Date.now() 和 Date.prototype.toISOString() 两个方法。
新增加 Function.prototype.bind() 方法,可以把一个函数、附加调用参数绑定为一个新函数:
1 2 3 4 5 |
function sayHello( who ) { console.log( 'Hello ' + who ); } var sayHelloToAlex = sayHello.bind(this,'Alex'); sayHelloToAlex(); // Hello Alex |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
// 静态方法of,将多个对象组合为数组 var array = Array.of( 1, 2, 3 ); console.log( array ); // [ 1, 2, 3 ] // 判断是否所有元素均能通过测试 array.every( function ( e ) { return !isNaN( e ); } ); // 判断是否至少一个元素均能通过测试 array.some( function ( e ) { return !isNaN( e ); } ); // 过滤数组元素,返回满足回调元素组成的新数组 var newarray = array.filter( function ( e ) { return e > 1; } ) // 遍历当前时刻数组包含的所有元素,被删除、未赋值(undefined)被自动跳过 array.forEach( function () { console.log( e ); } ) // 搜索元素出现的索引,使用严格比较(===,即值相等且类型相同) array.indexOf( 1 ); array.lastIndexOf( 3 ); // 针对每一个元素执行回调,由回调结果组成新数组 array.map( function ( e ) { return ++e; } ); // 指定一个累加器回调,从第一个元素开始调用回调,当前元素currentValue,上一次累加值为previousValue // 初始的累加值被设置为0 array.reduce( function ( previousValue, currentValue, index, array ) { return previousValue + currentValue; }, 0 ); |
JSON.parse() 用于解析字符串为JavaScript对象, JSON.stringify() 则将JavaScript对象转换为字符串。Boolean、Number、String、Date等类型添加了 toJSON() 方法。
记号 | 说明 |
$ | 根节点 |
@ | 当前节点 |
.或者[] | 子节点 |
.. | 所有符合条件的后代节点 |
* | 所有节点 |
[] | 迭代器标示,例如数组下标 |
[,] | 支持迭代器中进行多选 |
[start:end:step] | 数组切片 |
?() | 过滤操作 |
() | 进行表达式计算 |
JavaScrit对象都具有以下几个特性:
- 对象的原型(Prototype),原型本身是一个对象。当前对象从原型对象继承属性、方法。Object.prototype对象没有原型
- 对象的类型(Class),标记了对象的类别的字符串
对象可以分为以下几类:
- 内置对象(Native Object),由JavaScript语言定义的类型和对象,包括数组、函数、日期、正则式等
- 宿主对象(Host Object),由JavaScript解释器的宿主环境定义的类型和对象,例如Web浏览器定义的window
- 自定义对象,由JavaScript代码定义的类型和对象
对象的属性/方法可以分为:
- 自有属性(Own property),直接在对象中定义的属性
- 继承属性(Inherited property),通过原型链继承得到的属性
可以使用以下方式创建对象:
- 对象直接量语法: {} ,等价于 new Object()
- ES5引入的 Object.create() 调用
- new 关键字,后面跟着作为构造函数的函数调用
任何函数都可以作为构造函数使用,只要在调用时,附加 new 关键字。在构造函数里可以使用 this 关键字访问当前正被构建的对象。
构造函数的 prototype 属性指向一个对象,该对象即为通过此函数构造出的对象的原型对象:
1 2 3 4 5 6 7 8 9 10 |
function Fruit() { }; // 你可以直接设置prototype的属性,但是,如果你将其赋值为新的对象 Fruit.prototype = { typeId: 1 }; // 则一定要把此新对象的constructor设置为构造函数 Fruit.prototype.constructor = Fruit; console.log( new Fruit().typeId ); |
注意:尝试给内置类型(例如Array)的构造函数设置原型对象,可能无效。
构造函数的原型对象,可以设置为另外一个构造函数的原型对象,这样就可以形成“继承”。按照这种方式,一个原型可以有父原型、祖父原型……形成一个原型链条。原型继承(拷贝)来自祖代原型的属性、方法,自己可以覆盖之,或者定义新的属性、方法。
对于来自通过原型继承的、对象类型的属性,需要特别注意,继承的时候拷贝的是引用:
1 2 3 4 5 6 7 |
Fruit.prototype = { seeds: [] }; Fruit.prototype.constructor = Fruit; var f0 = new Fruit(); f0.seeds.push( 1 ); console.log( new Fruit().seeds ); // [ 1 ] 所有对象使用的是一个数组 |
1 2 |
// jQuery代码 field.attr("placeholder", "new placeholder content"); |
delete运算符在JavaScript中的作用是删除某个对象的属性(方法),不要与C++中的delete运算符混淆,后者用于清除指针指向的内存空间。
1 2 3 4 5 6 7 8 |
var person = { name: 'Alex', age : 20 }; delete person.age; console.log(person.age); //undefined delete person; //false,无法删除普通变量 |
此外需要注意,delete只是删除属性,属性指向的对象不会被删除,没有引用的对象会被垃圾回收器处理。
1 2 3 4 5 6 7 8 9 10 |
function plus (a, b){ return a + b; } // 在ECMAScript5的严格模式中,call()和apply()的第一个实参都会变为this的值,哪怕传入的实参是原始值甚至是null或undefined // 在ECMAScript3和非严格模式中,传入的null和undefined都会被全局对象代替,而其他原始值则会被相应的包装对象所替代 //第二个开始,逐个传入参数 plus.call(this, 1, 2); //第二个参数是实参的数组 plus.apply(this, [1, 2]); |
在Iframe的unload期间,添加类似如下代码:
1 2 3 4 5 6 7 8 9 |
if ( Ext.isIE ) { console.log( 'Cleaning up IE iframes...' ); var iframe = me.getFrame(); iframe.src = 'about:blank' iframe.contentWindow.document.write( '' ) CollectGarbage && CollectGarbage(); iframe.parentNode.removeChild( iframe ); } |
JavaScript引擎是单线程运行的, 浏览器无论在什么时候都有且只有一个线程在运行JavaScript程序
在JavaScript引擎运行脚本期间,浏览器渲染线程都是处于挂起状态的。某些实现下,这两者就是一个线程。
如果队列非空,引擎就从队列头取出一个任务,直到该任务处理完,即返回后引擎接着运行下一个任务,在任务没返回前队列中的其它任务是没法被执行的
javascript引擎线程、界面渲染线程、浏览器事件触发线程
Leave a Reply