• 设计模式之原型,学习笔记


      在常见的编程语言中如果你需要一个对象,那么可以通过类来创建,但是Javascript它并没有类这个概念,javascript创建对象是通过克隆另外一个对象而来的,既然如此那么它肯定有一个基类,这个基类就是Object.prototype,这是一个顶级根对象,其他所有对象都是通过克隆它而来的,比如你通过new Object()实际上就是克隆了Object.prototype。通过克隆我们可以得到一个一模一样的对象,但是这个prototype原型只有函数才有,因此我们得先创建一个函数,如下:

    function Fn(){
      this.name = 'JS';
    }
    Fn.prototype.sayHello = function(){
      alert(this.name);
    };

    var js = new Fn();
    console.log(js);

      这里我们用到了new ,实际上new干了两件事一个是把Fn里面的this指向了js另外一件事就是js的__proto__指向了Fn.prototype,__proto__属于隐藏的属性,但是谷歌浏览器和火狐浏览器控制台已经公开了。__proto__的作用就是,当你这个对象没有某些方法或者属性的时候,这个对象就会通过__proto__上面找,__proto__又指向了那个构造函数的prototype,因此它又跑去prototype上面找对应的属性或方法。

    下面我们手动模拟一下new的实现


    function createObj(fn){
      var obj = new Object();
      fn.call(obj); //通过call让fn里面的this指向obj
      obj.__proto__ = fn.prototype; //指向fn.prototype 继承方法和属性
      return obj;
    }
    console.log(createObj(Fn));


      new的内部实现可能要比这复杂,但大致是这样的一个过程。

      ES5提供了一种新的克隆对象方法它叫Object.create(对象);

    var obj = {a:1,b:2};
    var cloneObj = Object.create(obj);
    console.log(cloneObj);


      如果你通过谷歌浏览器你可以看到这样一个画面。


    Object {}
      __proto__: Object
        a: 1
        b: 2
        __proto__: Object

      也就是说这个Object.create这个方法实际上就是将cloneObj的__proto__指向了obj。Ok我们也来实现一个。

    var obj = {a:1,b:2};

    function createObj(obj){
      function Fn(){
      }
      Fn.prototype = obj;
      return new Fn();
    }
    console.log(createObj(obj));


      有可能你会奇怪,正如我之前郁闷一件事,就是为什么不直接return返回这个obj不就好了吗。


    var obj = {a:1,b:2};

    function createObj(obj){
      return obj;
    }
    console.log(createObj(obj));


      虽然你看上去没啥区别,但其实不是这样,实际上通过prototype并不是去真正的创建一个对象,而是继承,这很重要,如果你按照上面的那种错误做法是真的去创建了另一个对象了,这样的话内存中又多出来一个对象,而往往我们没有必要这样做,只是希望如果本身这个对象没有的话,我在去继承你那个对象,这样不岂妙哉。

      通过Object.create来创建对象多少和new Object()还是有区别的,首先Object.create支持传递一个null,如果传的是null的话,它创建的真的是一个彻彻底底的空对象,它的__proto__不指向任何东西,因此它不继承任何的属性和方法,而new Object()创建的它的__proto__指向Object.prototype,简单来说Object.create(null)没有原型,即一个空对象,而new Object()有原型对象。

  • 相关阅读:
    android 面试题
    android 入门-android Studio git 克隆
    android 入门-android自定义控件
    android 入门-控件 测量状态栏高度
    android 入门-android Studio git配置
    WPF 介绍一种在MVVM模式下弹出子窗体的方式
    WPF DataGrid分组和排序
    C# 等待框
    WPF 简洁的主界面
    C# 在WPF中使用Exceptionless异常日志框架
  • 原文地址:https://www.cnblogs.com/pssp/p/5786238.html
Copyright © 2020-2023  润新知