最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • JavaScript 面向对象(一):创建对象

    正文概述 掘金(闻朝)   2021-02-21   542

    JavaScript 是面向对象的,在 JavaScript 中我们可以通过多种手法来定义一个对象。

    基本手法

    首先你可以使用对象字面量“{}”,将这个字面量赋值给一个变量标识符后,就会生成一个对象,并且每次赋值都是一个新的对象,这也就意味着前后两次赋值的结果是不相等的,如

    let a = {};
    let b = {};
    a === b;  // false
    

    当前你也可以给对象加上初始值

    let a = {
    	value: '我是值'
    };
    

    通过上面的方式创建的对象即使不赋初始属性值,也是有一些属性在的,比如

    JavaScript 面向对象(一):创建对象

    如图可以看到“空对象” b 上有一个属性 proto,这是我们以后将要讨论的关键这里先不说。

    如果你想要一个真正的空对象,可以借助 Object.create() 函数

    let d = Object.create(null);  // 试试看吧
    

    这时候你会不会好奇,之前通过对象字面量创建时,多出来的那些属性是哪里来的呢?接下来揭晓答案

    初识 new

    JavaScript 中,所有符合对象定义的数据,最终的上层都可以溯源到 Object,换句话说所有对象的顶层都是 Object。在 JavaScript 中提供了一个关键字 new,你可以通过 new 关键字显式的调用 Object 函数来创建一个对象。

    let e = new Object()
    

    创建出来的结果如下图

    JavaScript 面向对象(一):创建对象

    对比发现,和通过对象字面量创建效果是一致的,并且可以猜测通过 new 调用 Object 每次创建的对象也是全新的不一样的对象

    JavaScript 面向对象(一):创建对象

    那么 new 关键字到底做了什么呢?

    认识 new

    ECMA262 标准中,对于 new 操作符的定义如下

    JavaScript 面向对象(一):创建对象

    通过图中可以看到 new 在使用时的语法是 new NewExpression 和 new MemberExpression Arguments,所以你可以这么使用

    let a = new Object;
    let b = new Object({a:1});
    

    new 操作符做的事情是:

    1. 语句执行时,创建一个新的空对象并且将该对象的 proto 属性链接到构造函数的 prototype
    2. 将新创建的对象作为构造函数的 this 指向,然后调用该构造函数
    3. 如果构造函数内部 return 一个新的对象,则返回该对象,否则返回这个创建的新对象

    知道了上述步骤,现在来验证一下:

    function demo1(){
      	this.a = 1;
        let b={b:1};
        return b;
    }
    
    function demo2(){
      this.a = 1;
    }
    
    let d1 = new demo1();
    let d2 = new demo2();
    

    运行上面的代码后,将得到如下的打印结果

    JavaScript 面向对象(一):创建对象

    可以看到,因为 demo1 函数中“return”了一个通过对象字面量创建的对象,所以最终得到的 d1 对象的 _proto _属性的 constructor 指向了 Object,而不是指向 demo1,并且这里 this.a 似乎也没有起效。

    而观察对象 d2 可以看到,d2 对象的 _proto _属性的 constructor 指向了 demo2,并且可以看到 this.a 起效了。这就验证了前面说到的三段步骤。

    你看,由于 demo1 内部有 return 一个新对象,new 操作符帮助我们创建的新对象没有用上,但是在执行构造函数的时候,又偏偏让函数执行时的上下文 this 指向了新的对象,所以 demo1 返回的结果上没有 a,而 demo2 没有 return 时是符合预期的。

    因此作为构造函数的函数,返回值必定不是对象。

    扩展

    我们知道,在函数里不写 return 相当于 return undefined ,所以又能够联想到 new 构造函数时,如果返回的结果不是一个对象会被忽略而返回 new 帮我们创建的变量,也正因此 String 这样的函数才既可以用来做构造函数,又可以用来作为类型转换函数。

    有些时候我们定义的函数出于某种目的会强制要求必须通过 new 调用,比如像 Promise,那么怎么来做这样的检查呢?重新思考之前说的 new 的执行步骤。

    new 在执行构造函数前,我们已经创建了一个新对象然后还让新对象的 _proto _属性指向了构造函数的 prototype(这是一个只有函数才拥有的属性,打印这个属性你就会发现它也是一个对象,其上有属性 constructor 和 proto ),在这之后将构造函数的 this 指向了新对象然后才执行构造函数。这也就意味着,我们可以在构造函数中通过 this 拿到这个新对象,然后去判断这个对象上的 constructor 是不是当前在执行的构造函数即可,如下所示:

    function demo3(){
      if(this.constructor !== demo3){
         throw new Error('本函数必须作为构造函数使用');
      }
    	this.a = 3;
    }
    

    你可以试试。

    模拟 new

    前面讲了 new 的执行过程,由于在 JavaScript 中 new 是一个操作符,我们是没法通过模拟的方式来真正的实现一个操作符的,但是我们可以通过实现一个函数来模拟 操作符的表现,如下所示:

    // 模拟函数
    function newFunc(fn){
        let newObj = Object.create(null);
        newObj.__proto__ = fn.prototype;
        return function(){
            let rt = fn.apply(newObj, arguments);
            return !rt || typeof rt !== 'object' ? newObj: rt;
        }
    }
    
    let demo6 = function(v1,v2,v3){
        this.v1=v1;
        this.v2=v2;
        this.v3=v3;
    }
    
    let d6 = newFunc(demo6)(1,2,3)
    

    注意,这里必须要说明的是,这只是在模拟操作,并没有说实现一个跟 new 一模一样的,这里 _proto _属性也是一个非标准化的属性,所以日常工作中不要使用 。

    总结

    1. 创建对象的手法有:对象字面量“{}”;Object.create();new Constructor
    2. 在实现构造函数时,如果有预期需要通过 new 来调用,则不要在函数内部返回一个对象
    3. new 的执行过程上面说了,不再赘述,不清楚的再回头看一下

    本篇讲了怎么创建对象,下一篇文章将会重点介绍对象上的 _proto 已经函数上的 _prototype 具体是什么。


    起源地下载网 » JavaScript 面向对象(一):创建对象

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元