JavaScript(一)

基于《JavaScript高级程序设计》


面向对象 OOP


  1. Object.defineProperty() 修改属性默认的数据特性或者访问器属性,接收三个参数:属性所在的对象,属性名,描述符对象(即数据特性或者get/set)

    数据特性有:

    • Configurable
    • Enumberable
    • Writable
    • Value

    访问器属性:只能调用Object.defineProperty()来实现

    • Configurable
    • Enumberable
    • Get: 在读取属性时,会自动调用
    • Set: 在写入属性时,会自动调用

    Object.defineProperties() 对一个对象同时定义多个属性

    Object.getOwnPropertyDescriptor() 取得给定属性的描述符

  2. 创建对象:

    • Object构造函数和字面量:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var person = new Object();
    // 对象字面量
    var person = {
    // 属性
    name = "James",
    age = 29,
    job = "Software Engineer",

    // 方法
    sayName: function(){
    // 这里的this显然被解析为person
    alert(this.name);
    }
    };

    • 构造函数模式

      i. 大写字母开头

      ii. 不显示创建对象,直接将属性或者方法赋给this对象

      iii. 无return语句

      iv. 使用new操作符创建新实例,并拥有constructor属性

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      function Person(name, age, job){
      this.name = name;
      this.age = age;
      this.job = job;

      this.sayName = function(){
      alert(this.name)
      };
      }

      // 调用
      var person = new Person("James", 28, "worker");
    • 原型模式:利用prototype属性,该属性是一个指针指向一个对象,该对象包含可以由特定类型的所有实例共享的属性和方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function Person(name, age, job){
    }

    Person.prototype.name = name;
    Person.prototype.age = age;
    Person.prototype.job = job;

    Person.prototype.sayName = function(){
    alert(Person.prototype.name);
    };

    // 调用
    var person = new Person("James", 28, "worker");

    Object.keys()接收一个对象名,返回可枚举属性的字符串数组,然后可以进行for-in循环
    Object.getOwnPropertyNames() 获取所有实例属性

    原型对象最大的问题就是它的所有属性都是被共享的,如果你的初衷不是这样的话,会引起很大的麻烦

    • 组合模型:构造函数定义实例属性,原型模式定义方法和需要共享的属性。
  3. 继承

    只支持实现继承(无接口继承)

    原型链:原型对象包含一个指向构造函数的指针,实例包含指向原型对象的内部指针。所以让原型对象等于另一个类型的实例,以此类推形成原型链。

  • 原型链基本模式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    function SuperType(){
    this.property = true;
    }

    SuperType.prototype.getSuperValue = function(){
    return this.property;
    };

    function SubType(){
    this.property = false;
    }

    // 原型对象等于另一个类型的实例,完成继承
    SubType.prototype = new SuperType();

    SubType.prototype.getSubValue = function(){
    return this.property;
    };

    问题:会存在由于原型模式导致的属性共享问题

  • 借用构造函数:

    即通过call()/apply()调用超类型的构造函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function SuperType(name){
    this.name = name;
    }

    function SubType(){
    SuperType.call(this, "James");

    this.age = 29;
    }

    var ins = new SubType();

    问题:构造函数引起的无法函数复用的问题

  • 组合继承

    使用原型链实现对原型属性和方法的继承,使用构造函数实现对实例属性的继承。

  • 寄生组合式继承

    1
    2
    3
    4
    5
    function inheritPrototype(subType, superType){
    var protoType = object(superType.prototype);
    protoType.constructor = subType;
    subType.prototype = prototype;
    }

    用该段替换为子类型原型赋值的语句,因为我们要的只是超类型原型的一个副本,没必要再去调用其构造函数。


函数表达式


  • 闭包是指有权访问另一个函数作用域的变量的函数。一般在一个函数中创建另一个匿名函数即形成了闭包。闭包会引用包含函数的整个活动对象,且不会随作用域链销毁。

  • 函数搜索this的值时只会搜索到活动对象为止。

  • 私有作用域(模仿块级作用域):

    1
    2
    3
    4
    5
    6
    // 最外面的括号是将函数声明转化为函数表达式
    // 结尾括号是执行函数
    (function(){
    // 这里是块级作用域

    })();
  • javaScript中没有私有成员,所有对象属性都是公开的,但有私有变量的概念:即函数的参数,局部变量和函数内部定义的其他函数。

    • 特权方法:用于访问私有变量或私有函数,一般为定义在函数内部的闭包(也有构造函数模式和原型模式)。
  • 模块模式:通过为单例添加私有变量和公有方法使其增强:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    var singleInstance = function{

    // 私有变量和私有函数

    var privateVar = 10;
    function privateFunction(){
    return false;
    }

    // 公有方法和属性
    // 以对象字面量返回
    return {
    publicProperty: true,

    publicMethod : function(){
    privateVar ++;
    return privateFunction();
    }
    }
    }

BOM(浏览器对象模型)


  • 核心对象:window 表示浏览器的一个实例,是访问浏览器的接口,也是Global对象。
  • 窗口本身尺寸:outerWidth, outerHeight, innerWidth, innerHeight

  • 导航和打开窗口

    window.open() : 接收4个参数:

    • 要加载的URL,
    • 窗口目标(已有窗口或框架的名称,加载到此中,没有则创建新窗口并命名)
    • 一个特性字符串(逗号分割的设置字符串,表示再新窗口中显示哪些属性)
    • 一个表示新页面是否取代浏览器历史记录中当前加载页面的bool值
  • 超时调用和间歇调用:

    setTimeout()/setInterval() :接收两个参数:

    • 执行的代码(一般直接传一个匿名函数,传字符串的话会造成性能损失(我的理解是先得解析字符串,然后根据解析后的结果才能执行表示的代码))

    • 超时时间(ms)

    返回一个ID,可调用clearTimeout(ID)/clearInterVal(ID)取消

  • 系统对话框:

    • alert() : 弹出包含一个按钮的对话框
    • confirm() : 点击OK表true, Cancel表false
    • prompt() : 接收两个参数,一个是提示你要输入什么内容,第二个是默认值。
  • location对象:提供与当前窗口中加载的文档有关的信息。包含多个属性

  • navigator对象:识别客户端浏览器的事实标准

  • history对象:可以前进和倒退历史界面 go()/back()/forward()


客户端检测


  • 能力检测/怪癖检测/用户代理字符串检测(也就涉及到一些字符串匹配的问题了)

这节似乎不是太重要 应该有封装好的现成的库吧。。