10.6.JS-继承模式,命名空间,对象枚举

262 阅读2分钟

1. 继承模式

  • 方法
  1. 传统形式 --> 原型链
  2. 借用构造函数
  3. 共享原型
  4. 圣杯模式
  • 具体实现
  1. 传统形式 --> 原型链
    • 过多继承了没用的属性
Grand.prototype.lastName = "Fun";
function Grand(){

}
var grand = new Grand();

Father.prototype = grand;
Father.prototype.fName = 'f';
function Father(){

}
var father = new Father();

Son.prototype = father;
Son.prototype.sName = 's'
function Son(){

}
var son = new Son();
console.log(son);
  1. 借用构造函数
    • 不能继承借用构造函数的原型
    • 每次构造函数都要多走一个函数
function Person(name, age, sex) {
  this.name = name;
  this.age = age;
  this.sex = sex;
}
function Student(name, age, sex, grade) {
  Person.call(this, name, age, sex);
  this.grade = grade;
}
var student = new Student('Fun', 25, 'male', '14'); // Student {name: "Fun", age: 25, sex: "male", grade: "14"}
  1. 共享原型
    • 不能随便动自己的原型
Father.prototype.lastName = 'Fun';
function Father(){

}
function Son(){

}
function inherit(Target,Origin){
  Target = Target || {};
  Target.prototype = Origin.prototype;
}
inherit(Son,Father);
var son = new Son();
//              prototype 
// Father                          Son
  1. 圣杯模式
function inherit(Target, Origin) {
  function F() { }
  F.prototype = Origin.prototype;
  Target.prototype = new F();
  Target.prototype.constructor = Target;
  Target.prototype.uber = Origin.prototype;
}
// YUI3 -- 雅虎 -- 圣杯模式
var inherit = (function () {
  var F = function () { };
  return function (Target, Origin) {
    F.prototype = Origin.prototype;
    Target.prototype = new F();
    Target.prototype.constructor = Target;
    Target.prototype.uber = Origin.prototype;
  }
}())

2. 命名空间

  • 管理变量,防止污染全局,适用于模块开发
  • 一般命名空间和 with(){} 结合使用
var org = {
  depart1: {
    fun1: {
      name: 'fun1'
    },
    fun2: {
      name: 'fun2'
    }
  },
  depart2: {
    fun3: {

    },
    fun4: {

    }
  }
}
var fun1 = org.depart1.fun1;
var fun2 = org.depart1.fun2;
console.log(fun1.name); // fun1
console.log(fun2.name); // fun2

3. 初始化函数

  • 初始化函数 -- 立即执行函数 -- 函数执行完清除内存 -- 返回的函数会保留作用域链[[scope]] -- 实现私有属性
var name = 'abc';
var init = (function () {
  var name = 'bcd';
  function callName() {
    console.log(name);
  }
  return function () {
    callName();
  }
}());
init(); // 'bcd' // 初始化函数 -- 立即执行函数 -- 函数执行完清除内存 -- 返回的函数会保留作用域链[[scope]] -- 实现私有属性

4. 实现链式调用

var fun = {
  smoke: function(){
    console.log('Smoking');
    return this;
  },
  drink: function(){
    console.log('drinking');
    return this;
  },
  perm: function(){
    console.log('perming');
    return this;
  }
}
fun.drink().smoke().perm(); // drinking Smoking perming

5. 对象枚举

5.1. 对象获取属性

var obj = {
  name: 'abc'
}
// obj.name ---> obj['name'] 等同

5.2. 对象读取属性

var obj = {
  book1: { name: 'js' },
  book2: { name: 'nodejs' },
  book3: { name: 'reactjs' },
  book4: { name: 'vuejs' },
  readBook: function (num) {
    return this['book' + num];
  }
}
console.log(obj.readBook(1).name); // js

5.3. 对象的枚举

  • for in
  1. hasOwnProperty
  2. in
  3. instanceof
  • 遍历 枚举 enumeration
// for循环
var arr = [1, 3, 4, 5, 6, 7, 8, 9];
for (var i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}
// for-in遍历
var obj = {
  name: 'fun',
  age: 25,
  sex: 'male',
  height: 180,
  weight: 75
}
for (var prop in obj) {
  console.log(prop + " " + typeof (prop));
  console.log(obj[prop]);
}
// for-in遍历会遍历原型链中非系统属性
var obj = {
  name: 'fun',
  __proto__: {
    lastName: 'teng'
  }
}
for (var prop in obj) {
  console.log(obj[prop]); // fun teng
}
// 使用hasOwnProperty可以不遍历原型链中的自定义属性
var obj = {
  name: 'fun',
  __proto__: {
    lastName: 'teng'
  }
}
for (var prop in obj) {
  if(obj.hasOwnProperty(prop)){
    console.log(obj[prop]); // fun
  }
}
  • 检测数据类型的四种方法:
    • typeof
    • instanceof
    • construtor
    • Object.prototype.toString.call() 识别this返回相应的结果

5.4. 克隆

5.4.1. 浅层克隆

function clone(origin,target){
  var target = Target || {};
  for(var prop in origin){
    target[prop] = origin[prop];
  }
  return target;
}

5.4.2. 深层克隆

function deepClone(origin, target) {
  var target = target || {},
    toStr = Object.prototype.toString,
    arrStr = "[object Array]";
  for (var prop in origin) {
    if (origin.hasOwnProperty(prop)) {
      if (origin[prop] != null && typeof(origin[prop]) == 'object') {
        if (toStr.call(origin[prop]) == arrStr) {
          target[prop] = [];
        } else {
          target[prop] = {};
        }
        deepClone(origin[prop], target[prop]);
      } else {
        target[prop] = origin[prop];
      }
    }
  }
  return target;
}