Javascript good parts 读书笔记

第三章 对象

  1. 引用传递

    javascript对象是通过引用来传递的,它们永远不会被拷贝.

  2. 属性委托

    尝试获取javascript对象的某个属性值,且该对象没有此属性名,那么javascript会试着从原型对象中获取属性值。如果那个原型 对象也没有该属性,那么再从他的原型中寻找,依次类推,直到该过程最后到达终点 Object.prototype . 如果想要的属性完全不存在于原型链中, 那么結果就是 undefined 值。这个过程称为委托.

  3. 反射
    • typeof

      确定属性的类型

      typeof flight.number //'number'
      typeof flight.status //'string'
      typeof flight.arrival //'object'
      typeof flight.manifest //'undefined'
      
    • hasOwnProperty(‘attribute’)

      如果对象拥有独有的属性, hasOwnProperty(‘attribute’)返回 true, 此方法不会检查原型链

  4. 枚举
    • POJO(暂且借用一下这个名词)

      直接使用 for in

    • 非POJO

      使用 typeof 和 hasOwnProperty() 来过滤掉不想要的属性

  5. 删除属性

    删除对象中的属性不会影响到原型对象中的属性, 但是会使原型对象中的属性暴露出来(因为属性委托机制)

    obj.nickname //'nick name in object'
    delete obj.nickname
    obj.nickname //'nick name defined in prototype'
    
  6. 减少全局变量污染

    有两种方法减少全局变量污染:

    • 将全局变量放在一个对象内部,说白了就是要使用命名空间
    • 使用闭包

第四章 函数

  1. 函数对象

    在javascript中,函数就是对象. 对象是”名/值”对的集合并拥有一个连接到原型对象的隐藏连接.

    对象字面量产生的对象连接到 Object.prototype . 函数对象连接到 Function.prototype (该原型对象本身连接到Object.prototype)

    !! 每个函数在创建时附有两个隐藏属性: 函数上下文 和 实现函数行为的代码.

    函数与众不同的之处最它们可以被调用

  2. 函数字面量

    函数字面量的创建:

    • 保留字 function
    • 函数名 (可以省略)
    • 函数参数
    • 函数体

    通过函数字面量创建的函数包含有一个连接到外部上下文的连接,这被称为闭包

    闭包是javascript强大表现力的根基

  3. 调用

    函数被调用时会接收两个参数: this 和 arguments, 其中 this 的值取决于调用的模式.

    (传入参数包含this与python的对象方法非常的类似,只不过javascript不需要形参来显式接收this, 而python强制要求第一个形参接收传入的this引用(按惯例,这个引用一般叫self)

    javascript的this引用是javascript之所以如此灵活的根基(我是这样想的), 利用this可以实现方法的高度复用.

    四种方法调用模式:

    • 方法调用模式

      当一个函数被保存为对象的一个属性时,我们称它为一个方法(看来方法与函数还是有区别的). 当方法被调用时, this 被绑定到该对象. this到对象的绑定发生在调用的时候,这个超级迟绑定(very late binding)使得函数可以对this高度利用. 通过 this可取得它们所属对象的上下文的方法被称为公共方法.

    • 函数调用模式

      当一个函数并非一个对象的属性时,那么它被当作一个函数来调用. 当函数以此模式被调用时, this被绑定到全局对象– 这是语言设计的一个错误.这个错误设计的后果就是方法不能利用内部函数来帮助它工作, 因为内部函数的this被绑定了错误的值, 所以不能共享该方法对对象的访问权.

      可以通过 that = this 来解决 (命令为that是约定)

    • 构造器调用模式

      (曾经是我最常用的一种方式, 现在看来我错了很久...) 一种模糊了javascript原型本质的,类似基于类的语言的对象构建语法, 一种两边不讨好的语法. (a. 模糊了原型本质 b. 不伦不类的基于类的对象构造语法)

      按照约定, 构造器首字母要大写.

      new 前缀创建出一个空白对象, 把这个空白对象作为构造器函数的this引用传入, 在构造器函数内对这个对象进行一些操作.

      function Person(){
          var name = 'steven';
          var age = '24';
      
          this.getPersonInfo = function(){
              return name + '-' + age;
          };
      
          this.sayHi = function(){
              print('hello, ' + this.getPersonInfo());
          }
      }
      
      var person = new Person();
      
      print(person.getPersonInfo());
      

    这种形式没有使用原型继承, 全部都是方法的复制, 每个新创建的对象都从构造器函数中一份完全相同的属性值, 增大了系统开销.

    不推荐这种调用模式

    • apply 模式

      javascript函数隐式传入this引用正是为apply调用模式服务的. 调用形式: functionName.apply(objectReference, arguemnts) 以objectReference为引用, arguments为函数去执行functionName函数.

      call与apply功能相同,不同之处是apply以数组形式给函数传入参数,而call将多个参数一一例举出来传递.

      var sum = add.apply(null,[2, 3]);
      var sum2 = add.call(null,2,3);
      
  4. 参数

    函数中的arguments可以获取传给函数的所有参数, 但是arguments的实现是又一个javascript语言实现的错误, arguments只是一个类数组(array-like), 拥有length属性, 但是缺少所有的数组方法

  5. 返回

    javascript函数总会返回一个值,如果没有明确使用return语句,则返回undefined.

  6. 异常

    javascript可以使用throw语句抛出一个异常(是一个对象直接量), 异常对象会传递给 catch 子句.

  7. 给类型添加方法(修改类型对象的原型)

    Number.prototype.add = function(){
        return this + arguments[0];
    }
    
    print((2).add(5)); // 7
    
  8. 作用域

    function级别的作用域. 在一个function内部定义的变量在function内部的任何地方都可见.

  9. 闭包

    闭包: 一个函数字面量持有外部的上下文环境. 上下文环境指的是, 外部函数中定义的变量和外部函数接收的参数.

    闭包的常见写法:

    • 返回一个对象直接量
    • 返回一个匿名函数
  10. 模块模式

    一般形式:

    1. 一个定义了私有变量和私有函数的函数
    2. 利用闭包创建可以访问私有变量和私有函数的特权函数(或对象)
    3. 最后返回这个特权函数(或对象)
  11. 级联

    (jQuery链式写法全是级联), 级联操作的每个方法返回 this 而不是 undefined

  12. 套用

    函数也是值,从而我们可以用有趣的方式来操作函数值. 套用允许我们将函数与传递给它的参数相结合去产生一个新的函数.

    Object.prototype.method = function (name, func) {
        this.prototype[name] = func;
        return this;
    }
    
    
    Function.method('curry', function(){
                // args represents arguemnts pass to curry function
                // that represents the original function object
                var slice = Array.prototype.slice;
                var args = slice.apply(arguments), that = this;
                //using closure to keep above value
                return function() {
                    var param = slice.apply(arguments).concat(args);
                    that.apply(null, param );
                }
            });
    
    function add() {
        print(arguments[0] + arguments[1]);
        return arguments[0] + arguments[1];
    }
    
    var addWith1 = add.curry(1);
    addWith1(6); // 7
    

Table Of Contents

Previous topic

JavaScript Programming

Next topic

Java Server Faces

This Page