【有书共读】《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();
}
};
}();#读书笔记##设计##笔记#
查看1道真题和解析