JS干货--拷贝与继承

浅拷贝与深拷贝

  -------------
    浅拷贝
  -------------
  var obj = {
    name: 'name'
  }
  var a = obj;
  a.name = 'new name';
  console.log(a.name); // 'new name'
  console.log(obj.name); // 'new name'

  这里就是一个浅拷贝的例子。a只是通过赋值符号得到了obj的引用。

  ---------------
    深拷贝
  ---------------
  function object(parent, child) {
    var i,
        tostring = Object.prototype.toString,
        aStr = "[object Array]";
    child = child || {};
    for(i in parent) {
      if(parent.hasOwnProperty(i)) {
        //这时候还要判断它的值是不是对象
        if(typeof parent[i] === 'object') {
          child[i] = tostring.call(parent[i]) === aStr ? [] : {};
          object(parent[i], child[i]);
        }
        else {
          child[i] = parent[i];
        }
      }
    }
    return child;
  }
  var obj = {
    tags: ['js','css'],
    s1: {
      name: 'dai',
      age: 21
    },
    flag: true
  }
  var some = object(obj);
  some.tags = [1,2];
  console.log(some.tags); //[1, 2]
  console.log(obj.tags); //['js', 'css']  

  这里可能有一些写法,对于新手不太友好,可以看看我前面的文章(^_^)。

  上面只是对于单个对象的深拷贝,那么这里要引入多个对象拷贝的需求(mixin):
  function mixIn() {
    var i,
        slice = Array.prototype.slice,
        args = slice.call(arguments),
        result;

    for(i = 0, max = args.length; i < max; i++) {
      result = object(args[i], result);
    }

    return result;
  }
  var a = {
    tags: [1,2,3]
  }
  var b = {
    b1: {
      name: 'no name',
      age: 21
    }
  }
  var c = mixIn(a, b);

  是不是很棒,重用了很多代码。

JS中的继承模式。

首先大家要明白原型链,原型链简单解释。让你要记住prototype只能指向对象,不能指向函数。

  ----------------
    method 1
  ----------------
  function inherit(Child, Parent) {
    Child.prototype = new Parent();
  }
  function Parent(name) {
    this.name = name || 'no name';
  }
  Parent.prototype.say = function () {
    console.log(this.name + ' say hi !');
  }
  function Child() {}
  inherit(Child, Parent);
  var c = new Child();
  c.say(); // 'no name say hi'

  这种方法通过原型指向父类的实例,得到继承的效果,需要注意的:
  1、对于父类构造器中的属性,我们没有办法赋予初始值。例如:
    var c = new Child('dai')
    c.say(); // 'no name say hi'
  2、这里如何找到say方法的。
    c.__proto__.__proto__ === Parent.prototype

  ------------
    method 2
  ------------
  function Father() {
    this.fMoney = 50;
    this.say = function () {
      console.log('father');
    }
  }
  function Mother() {
    this.mMoney = 2000;
  }
  function Son() {
    Father.call(this);
    Mother.call(this);
    this.hasMoney = function () {
      return this.fMoney + this.mMoney;
    }
  }
  var s = new Son();
  s.hasMoney(); // 2050
  s.say(); // "father"

  这里采用了call方法,和它拥有差不多功能的还有apply和bind。这三个函数还是很重要的。
  需要的注意的是:
  1、我们将say方法定义Father构造器中,消耗内存。


  ---------------------------
    method 3(综合上面两种方法)
  ---------------------------
  function Parent(options) {
    options = options || {};
    this.name = options.name || 'no name';
    this.age = options.age || 0;
  }

  Parent.prototype.say = function () {
    console.log(this.name + ' say hi!');
  }

  function Child(options) {
    options = options || {};
    //调用父类的构造方法
    Parent.call(this,options);
    this.job = options.job || 'no job';
  }
  //继承原型链
  Child.prototype = Object.create(Parent.prototype);
  //重新指定构造器方法
  Child.prototype.constructor = Child;

  Child.prototype.work = function () {
    console.log('work start');
  }
  var c = new Child({name: 'dai', age: 24, job: 'coder'});
  c.say(); // 'dai say hi!'
  c.work(); // 'work start'
  console.log(c.age); // 24
  console.log(c.job); // 'coder'

  这种写法还是比较好理解的,而且我也比较喜欢这样的写法。

  -------------
    模仿类
  -------------
  var jlass = function(Parent, props) {
    var Child,
        F = function () {},
        i;

    Child = function () {

      if(Child.uber && Child.uber.hasOwnProperty("__construct")) {
        Child.uber.__construct.apply(this, arguments);
      }
      if(Child.prototype.hasOwnProperty('__construct')) {
        Child.prototype.__construct.apply(this, arguments);
      }
    }

    Parent = Parent || Object;
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.uber = Parent.prototype;
    Child.prototype.constructor = Child;

    for(i in props) {
      if(props.hasOwnProperty(i)) {
        Child.prototype[i] = props[i];
      }
    }

    return Child;
  }

  var People = jlass(Object, {
    __construct: function (options) {
      options = options || {};
      this.name = options.name || 'no name';
      this.age = options.age || 0;
    },
    say: function () {
      console.log(this.name + ' ' + this.age);
    }
  })

  var Man = jlass(People, {
    __construct: function (options) {
      options = options || {};
      this.sex = options.sex || 'no';
    },
    intro: function () {
      console.log(this.name + ' ' + this.age + ' ' + this.sex);
    }
  })
  var man = new Man({name: 'dai', age: 24, sex: '男'});
  man.say(); // 'dai 24'
  man.intro(); // 'dai 24 男'

  虽然JavaScript可以模仿这样的类,但是感觉变成了另一种语言了。(*_*)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值