【有书共读】《JS高级程序设计》读书笔记02
6.第六章
ECMASCript中没有类的概念,每个对象都是基于一个引用类型创建的。
6.1理解对象
最简单方法,创建一个Object实例。
var person = new Object(); person.name = "seal"; person.sayName = function(){ alert(this.name); } // 也可以这样写 var person = { name: "seal", sayName: function(){ alert(this.name); } }
6.1.1属性类型
- 数据属性
- Configurable: 能否通过delete删除
- Enumberable: 能否通过for-in 枚举
- Writable: 能否修改属性值
- Value: 数据值
- 访问器属性
- get: 读取访问器属性时调用
- set: 修改访问器属性时调用
Configurable属性被设置为false后就不可被再次更改。
6.1.2 定义多个属性
Object.defineProperties()
6.1.3 读取属性的特性
Object.getOwnPropertyDescriptor()
6.2 创建对象
6.2.1 工厂模式
function createObject(name, age){ var o = new Object(); o.name = name; o.age = age; o.sayName = function(){ alert(this.name); }; return o; }
6.2.2 构造函数模式
function Person(name,age){ this.name = name; this.age = age; this.sayName = function(){ // do something } } var person1 = new Person('seal', 24);
new 操作符的过程
- 创建一个空对象
- 将this指向这个新对象
- 执行构造函数
- 返回新对象
检测对象类型
- instanceof
alert(person1 instanceof Object); // true alert(perosn1 instanceof Person); // true
构造函数的缺点
- 每个方法都要在每个实例上重新创在一遍。
6.2.3 原型模式
我们创建的每个函数都有prototype属性,指向它的原型,这个原型用于定义所有实例共享的属性和方法。
function Person(){ } Person.prototype.name = "seal"; Person.prototype.sayName = function(){ // do something }使用hasOwnProperty()方法检测一个属性是来自原型还是来自实例
- person1.hasOwnProperty("name")
- 返回true,来自实例
使用 in 操作符,无论来自对象还是原型都返回true。
问题
- 引用类型的属性会被所有实例共享
6.2.4 组合使用构造函数模式和原型模式
6.2.5 动态原型模式
6.2.6 寄生构造函数模式
6.2.4 稳妥构造函数模式
6.3 继承
各种方式的缺点...(见书本中)
常用组合继承:
function SuperType(name) { this.name = name; this.color = ['red', 'blue', 'green']; } SuperType.prototype.sayName = function () { console.log(this.name); } function SubType(name, age) { SuperType.call(this, name); this.age = age; } SubType.prototype = new SuperType(); SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function () { console.log(this.age); } var instance = new SubType('seal', 18); instance.sayName(); // seal instance.sayAge(); // 18
第七章
定义函数的方式有两种:一种是函数声明,另一种就是函数表达式。
//函数声明 function functionName(arg0, arg1, arg2) { //函数体 } //函数表达式 var functionName = function(arg0, arg1, arg2) { //函数体 }
函数声明的一个重要特征就是函数声明提升。
递归
var factorial = (function f(num) { if(num <= 1) { return 1; } else { return num * f(num-1); } });
以上代码创建了一个名为f()的命名函数表达式,然后将它赋值给factorial。即便把函数赋值给了另一个变量,函数的名字f仍然有效,所以递归调用照样能正确完成。
闭包
闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数,例如:
function createComparisonFunction(propertyName) { return function (object1, object2) { return object1[propertyName] - object2[propertyName]; }; }
闭包与变量
闭包只能取得包含函数中任何变量的最后一个值。闭包所保存的是整个变量对象,而不是某个特殊的值
function createFunctions() { var result = new Array(); for(var i = 0; i<10; i++) { result[i] = function() { return i; }; } return result; }
可以通过创建另一个匿名函数强制让闭包的行为符合预期
function createFunctions() { var result = new Array(); for(var i = 0; i < 10; i++) { //匿名函数直接赋值 result[i] = function(num) { return function() { return num; }; }(i); } return result; }
this对象
this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。匿名函数的执行环境具有全局性,因此其this对象通常指向window。
var name = "The Window"; var object = { name: "My Object", getNameFunc: function() { return function() { return this.name; }; } }; alert(object.getNameFunc()()); //"The Window"(在非严格模式下) getNameFunc()返回一个匿名函数,因此object.getNameFunc()()就会立即调用它返回的函数,结果就是返回一个字符串"The Window"。而如果访问object的属性,就需要把外部作用域中的this对象保存在一个闭包能够访问到的变量里。如下: var name = "The Window"; var object = { name: "My Object", getNameFunc: function() { var that = this; return function() { return that.name; }; } }; alert(object.getNameFunc()()); //"My Object"
模仿块级作用域
JavaScript 中没有块级作用域的概念。这意味着在块语句中定义的变量,实际上是在包含函数中而非语句中创建的
function outputNumbers(count) { for(var i=0; i<count; i++) { alert(i); } alert(i); //计数 }
私有变量
function MyObject() { //私有变量和私有函数 var privateVariable = 10; function privateFunction() { return false; } //特权方法 this.publicMethod = function() { privateVariable++; return privateFunction(); }; }
静态私有变量
(function() { var name = ""; Person = function(value) { name = value; }; Person.prototye.getName = function() { return name; }; Person.prototype.setName = function(value) { name = value; }; })(); var person1 = new Person("Nicholas"); alert(person1.getName()); //"Nicholas" person1.setName("Greg"); alert(person1.getName()); //"Greg" var person2 = new Person("Michael"); alert(person1.getName()); //"Michael" alert(person2.getName()); //"Michael"
以这种方式创建静态私有变量会因为使用原型而增进代码复用,但每个实例都没有自己的私有变量。
模块模式
var singleton = { name : value, method : function() { //这里是方法的代码 } };
模块模式通过为单例添加私有变量和特权方法能够使其得到增强,其语法格式如下:
var singleton = function() { //私有变量和私有函数 var privateVariable = 10; function privateFunction() { return false; } //特权/公有方法和属性 return { publicProperty: true, publicMethod: function() { privateVariable++; return privateFunction(); } }; }();#读书笔记##设计##笔记#