• 深入JS第一天:原型和它的小伙伴们(一)


     我在这里不说定义,找点问题,再解决问题。

    一、原型


    Q1:这样做输出的结果是什么?

          jQuery= String;
          jQuery.prototype.say = function () {
              alert('呵呵');
          };
          var jj = new String();
          jj.say();//String是否会有这种方法?

    A1:运行之后我们发现,在JQuery中的修改导致了String对象原型的变更。所以我们可以得出结论,如果两个对象相等,那么它们会共用原型,一方进行操作,另一方也会因此改变。

    Q2:比较一下上下两段代码有什么不同?

          jQuery = function () { };
          funcProto = function () { };
          jQuery.prototype= funcProto;
          funcProto.say = function () {
              alert('呵呵');
          };
          var js = new jQuery();
          js.say();
          //---------------华丽的分割线----------------
          funcProto = jQuery.prototype;
          funcProto.say = function () {
              alert('呵呵');
          };
          var js = new jQuery();
          js.say();

    A2:我们在运行之后就会发现,这二者没有什么区别。我们发现,原型不是一个只读的属性,是可读写的。

    Q3:下面的代码有区别么?

    jQuery = function () { };
          funcProto = function () { };
          jQuery.prototype.constructor = funcProto;
          funcProto.prototype.say = function () {
              alert('呵呵');
          };
          var js = new jQuery();                                                                                
          js.say();//只写constructor后会输出什么?
          //------------------------------------------
          funcProto = jQuery.prototype.constructor;
          funcProto.prototype.say = function () {
              alert('呵呵');
          };
          var js = new jQuery();
          js.say();//只读constructor后这又是啥?

    A3:这时我们会发现区别:上面会报错,而下面却输出正常了。想必大家对constructor这个属性的含义并不陌生,通过这个实验我们可以认识到,原型的属性是可读写的,可是在只读和只写时出现了差别。所以我们要注意:在面向对象书写JavaScript的时候,有必要再写完后,重新再确认一次原型中的constructor的指向,否则有时会出现指向错误。为什么上半部分就会失败呢?接着往下看。

    Q4:上个问题我们讨论了更改属性不能改变对象性质,那么我们试着去改变对象实例的Constructor的原型呢?

    var jj = new String();
    jj.constructor.prototype = Array.prototype;
    alert(jj.constructor);
    String.prototype = Array.prototype;
    var jj = new String();
    alert(jj.constructor);

    A4:我们发现输出false,一个string类型的实例在改写了它的constructor的原型后并没有变成Array类型。而直接更改原型也不行,我们可以得知JavaScript规定,基本类型(Array String Number Function Object RegExp Date等JavaScript引擎中封装好的‘类’)的构造器的原型是只读的,不能赋值。

    Q5:看看__proto__指针都指向什么?

          alert(String.constructor.prototype === Array.constructor.prototype);//true
          alert(String.__proto__ === Array.__proto__);//true
          var str = '';
          var arr = [];
          alert(str.__proto__);
          alert(arr.__proto__);
          str.__proto__ = arr.__proto__;
          alert(str.__proto__ === arr.__proto__);//false

    A5:通过实验我们知道,__proto__指针其实就是constructor.prototype,下面的str.__proto__ = arr.__proto__操作是不是和Q4中的String.prototype=Array.prototype一样?所以我们得出结论,constructor.prototype属性是只读的。

    现在我们应该能够知道Q3的问题所在,当我们在设置obj2.prototype.constructor=obj的时候却是可读写的,但是更改obj的prototype并不能回推到obj2,我们如果给obj和obj2判等,发现其实二者并不一样。因为obj2的实例的__proto__指针早已设定好指向obj2.prototype,所以Q3上半部分不能成功。而Q3下半部分之所以成功,是因为obj=obj2.prototype.constructor时,obj和obj2指针已经相等,所以改obj和改obj2是等效的。

  • 相关阅读:
    Codeforces Round #717 (Div. 2)
    Codeforces Round #716 (Div. 2)
    atCoder Regular Contest 117
    Codeforces Round #715 (Div. 2)
    牛客挑战赛49
    从零开始搭建webpack应用
    扫盲:npm
    MYSQL安装
    Int和integer区别
    关于JDK配置以及DOS窗口执行指令
  • 原文地址:https://www.cnblogs.com/JhoneLee/p/3650466.html
Copyright © 2020-2023  润新知