分享

JavaScript学习笔记【4】类和模块、子集和扩展

 quasiceo 2015-03-20

JavaScript学习笔记【4】类和模块、子集和扩展

笔记来自《JavaScript权威指南(第六版)》

包含的内容:

  • 类和模块
  • JavaScript的子集和扩展

类和模块

在JavaScript中,类的所有实例对象都从同一个原型对象上继承属性。因此,原型对象是类的核心。

定义构造函数既是定义类,并且类名首字母要大写。而普通的函数和方法都是首字母小写的。

任何JavaScript函数都可以用做构造函数,并且调用构造函数是需要用到一个prototype属性的。因此,每个JavaScript函数都自动拥有一个prototype属性。这个属性的值是一个对象,这个对象包含唯一一个不可枚举属性constructor。

对于任意函数F.prototype.constructor == F

JavaScript中的函数都是以值的形式出现的,方法和字段之间并没有太大的区别。如果属性值是函数,那么这个函数就定义一个方法;否则,它只是一个普通的属性或“字段”。

JavaScript中基于原型的继承机制是动态的:对象从其原型继承属性,如果创建对象之后原型的属性发生改变,也会影响到继承这个原型的所有实例对象。

可以给Object.prototype添加方法,从而使所有的对象都可以调用这些方法。但是这种做法无法将这些新增加的方法设置为不可枚举的。可以使用Object.defineProperty()方法安全地扩充Object.prototype。

instanceof检测对象是否是属于某个类的构造函数,不一定是直接继承。

构造函数是类的公共标识,当原型是唯一的标识。

如果想检测对象的原型链上是否存在某个特定的原型对象,可以使用isPrototypeOf()方法。

Instanceof和isPrototypeOf()的缺点是,我们无法通过对象来获得类名,只能检测对象是否属于指定的类名。

另一个识别对象是否属于某个类的方法是使用constructor属性。

使用构造函数的名字而不是构造函数本身作为类标识符。在一些JavaScript的实现中为函数对象提供了一个非标准的属性name,用来表示函数的名称。

【图】可以判断值的类型的type()函数。

 

鸭式辩型:如果一个对象可以像鸭子一样走路、游泳并且嘎嘎叫,就认为这个对象是鸭子,哪怕它并不是从鸭子类的原型对象继承而来的。

ValueOf()用来将对象转换为原始值。

toJSON()由JSON.stringify()自动调用的。JSON格式用于序列化良好的数据结构,而且可以处理JavaScript原始值、数组和纯对象。它和类无关,当对一个对象执行序列化操作时,它会忽略对象的原型和构造函数。

JSON.parse()将字符串转化为纯对象,不包含继承来的方法。

方法借用,也叫做“多重继承”,把一个类的方法用到其他的类中的做法。

如:Range.prototype.equals = generic.equals;

私有实例字段,只能被类的实例方法访问,且在类的外部是不可见的。

可以通过将变量(或参数)闭包在一个构造函数内来模拟实现私有实例字段,调用构造函数会创建一个实例。为了做到这一点,需要在构造函数内部定义一个函数(因此这个函数可以访问构造函数内部的参数和变量),并将这个函数赋值给新创建对象的属性。

使用闭包来封装类的状态的类一定会比不使用封装的状态变量的等价类运行速度更慢,并占用更多的内存。

B.prototype = inherit(A.prototype); //子类派生自父类

B.prototype.constructor = B; //重载继承来的constructor属性

这两行代码是在JavaScript中创建子类的关键。如果不这样做,原型对象仅仅是一个普通对象,它只继承自Object.prototype,这意味着你的类和所有的类一样是Object的子类。

定义子类时,我们往往希望对父类的行为进行修改或扩充,而不是完全替换掉它们。为了做到这一点,构造函数和子类的方法需要调用或链接到父类构造函数和父类方法。

Object.defineProperty()和Object.defineProperties()可以用来创建新属性,也可以修改已有属性的特性。当用它们创建新属性时,默认的属性特性的值都是false。但当用它们修改已经存在的属性时,默认的属性特性依然保持不变。

通常认为,通过给原型对象添加方法可以动态地对类进行扩展,这是JavaScript本身的特性。ECMAScript 5可以根据需要对此特性加以限制。

Object.preventExtensions()可以将对象设置为不可扩展的,也就是说不能给对象添加任何新属性。

Object.seal()则更加强大,它除了能阻止用户给对象添加新属性,还能将当前已有的属性设置为不可配置的。这样就不能删除这些属性了,但不可配置的属性可以是可写的,也可以转换为只读属性。Object.seal(Object.prototype)。

一般来讲,模块是一个独立的JavaScript文件。模块文件可以包含一个类定义、一组相关的类、一个实用函数库或者是一些待执行的代码。

在模块创建过程中避免污染全局变量的一种方法是使用一个对象作为命名空间。它将函数和值作为命名空间对象属性存储起来(可以通过全局变量应用),而不是定义全局函数和变量。

如果想让代码在一个私有命名空间中运行,只需要把代码放在如下的位置。使用了立即执行的匿名函数。

(function(){

/*代码*/

}())

JavaScript的子集和扩展

子集的定义大部分都是出于安全考虑,只有使用这门语言的一个安全的子集编写脚本,才能让代码执行地更安全、更稳定,比如如何更安全地执行一段由不可信第三方提供的广告代码。

为了让JavaScript代码静态地通过安全检查,必须移除一些JavaScript特性:


安全子集:ADsafe、dojox.secure、Caja、FBJS、Microsoft Web Sandbox、

const pi = 3.14; //定义一个常量并赋值

关键字let有4种使用方式:

1、  可以作为变量声明,和var一样;

2、  在for/in循环中,作为var的替代方案;

3、  在语句块中定义一个新变量并显式指定它的作用域;

4、  定义一个在表达式内部作用域中的变量,这个变量只在表达式内可用。

JavaScript扩展:解构赋值、迭代器、生成器yield、数组推导、函数简写、多catch从句。。。

文档信息

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多