js 面向对象问题:为什么用不用new都一样呢?

s= {
"a":111
}

ss = {
    "sss" : {
        "set":function(num){
            this.a=num
            return this
        },
        "a":222
    }
}

Object.setPrototypeOf(ss.sss, s);

alert(new ss.sss.set(333).a+'--'+new ss.sss.set(555).a);
alert(ss.sss.set(333).a+'--'+ss.sss.set(555).a);

1.两个alert的执行结果为什么是一样的呢?
2.为什么new 和没new 一样呢?
3.没new是一个独立的对象吗?
4.如果效果一样,没用new是不是更省内存呢?

答案公布,因为函数里有return返回对象了,所以不需要new,如果写new 就不必返回对象,重复了!还有没new的和new的一样,没有哪个更省内存,因为new包括了return 对象就真么简单,感谢问题下面的评论者的链接

阅读 4.7k
6 个回答
  1. new ss.sss.set(333).anew ss.sss.set(555).a这两个操作, 得到的this不是ss对象, 而是set的实例. 这里的this.__proto__ === ss.sss.set.prototype. 这里的this.ass.sss无关, 是新实例的this.a. 返回新实例, 访问其a属性, 就会得到刚才设置的a属性.

  2. ss.sss.set(333).ass.sss.set(555).a这两个操作, 因为没有使用new, 所以这里的this指向的是ss.sss, 所以修改的是ss.sss.a. 因为ss.sss.set返回的是this, 所以这里的ss.sss.set(333).a实际上就是ss.sss.a.

综上, 实际上你两种方式(用或不用new), 得到的对象并不是同一个对象, 而是不同的对象.

set函数内部有return this;用new调用时返回的是set的实例,实例中有a属性,函数调用时this指向时sss,返回的是sss,是在sss中创建了a属性,已经改变了sss。

就代码来讲:

后面的alert你应该是懂的,第一个的话,new ss.sss.set(333),返回一个set { a:333 },故自然是333了。

我理解题主在想什么,但你的DEMO无法体现,因为 new ss.sss.set 实例的是 set 函数,所以不管 newnew 都无法达到你想要的结果,包括 Object.setPrototypeOf(ss.sss, s); 也是一句摆设;题主可以加一句代码,你就明白这个错误了。

                "set": function (num) {
                    console.log(this.a);
                    this.a = num
                    return this
                },

但也不是都无法解释你的四个问题。

首先,不管 s 还是 ss 他们都是一个 Object 类型,而对于 Object 类型是无法被构造的,我想你在写这个DEMO的时候,应该也尝试写了 new ss.sss() 吧,然后实在没办法了,才写了 new ss.sss.set()

以上的回答,从侧面解释你的前三个问题。

而对于,后一个问题,涉及到关于 new 后面做了哪些事?

以下面代码为准的情况下:

function User() {}
let u = new User();

创建一个实例的时候会两个过程:

1、构造 User 函数的时候,会把 u 以传参的形式传递给构造函数,并替换 this
2、设置原型链。

精妙之处在于原型链,当然,其中一个好处与你说的一样,更内存;但,这还包括更省代码、更奇妙!

以上。

加了个console.log(this)

这样就知道this的指向了,第一个是set,第二个是sss,sss原型链上有a属性,因为Object.setPrototypeOf(ss.sss, s);

  • new ss.sss.set(333).anew ss.sss.set(555).a)中,因为是new操作,所以这里set的调用是构造函数的调用,this指向一个新的实例,该实例中的a在构造函数中被赋值,set return出来的this是这个实例。

  • ss.sss.set(333).ass.sss.set(555).a)中,set是作为对象中方法来调用,this指向的是调用他的对象sss,方法体中给this.a赋值也就是修改了sss对象的a属性,return出来的是this是sss。

  • 因为set方法体中为this.a赋值,而return的又是this,那之后链式获取a,两次alert当然也就和你方法体中赋给a的值也就是你传入的参数都一样了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题