【有书共读】《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();
        }
    };
}();
#读书笔记##设计##笔记#
全部评论

相关推荐

牛客771574427号:恭喜你,华杰
点赞 评论 收藏
分享
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务