javascript - JS 使用“构造函数”和“内置对象(Object)”创建对象有什么区别?
PHP中文网
PHP中文网 2017-04-11 12:38:58
0
7
1128
var myArr = Object();
myArr.name = "javascript";
myArr.age = 2017;
console.log(myArr);//Object {name: "javascript", age: 2017}
console.log(typeof myArr);//object
console.log(myArr.name);//javascript

function Fun(){}

var a = new Fun();
a.name = "javascript";//去掉new后,Cannot set property 'name' of undefined
a.age = 2017;//去掉new后,Cannot set property 'age' of undefined
console.log(a);//Fun {name: "javascript", age: 2017}
console.log(typeof a);//object
console.log(a.name);//javascript

上面代码中,使用“内置对象Object”创建对象,可以不使用new,Array也可以不使用new。

但是使用构造函数创建对象的话,如果不使用new就只是一个函数的返回值,也无法创建属性。

在我的理解,他们都是对象,为什么创建的时候就有区别了呢?

这是不是因为“Object”本来就是对象,而构造函数是通过函数封装的对象的原因呢?

我也不知道为什么我会有好多千奇百怪的问题。。。

PHP中文网
PHP中文网

认证高级PHP讲师

全部回复(7)
左手右手慢动作

Object 里面有判断有没有写 new 的代码。如果没写就返回 return new Object()。在你的 Fun 里面也可以添加。比如:

也可以

function _Fun_() {}

function Fun(){
 // 这样 new Fun() 和 Fun() 就没有区别了。
  return new _Fun_();
}

详见
http://zonxin.github.io/post/...

Peter_Zhu

不是很理解你的问题。。我说几点,希望对你有帮助~

  • ObjectFun一样是一个函数,他们本质上是Object类型的

  • 直接调用 a = Fun(),称之为一般函数调用,而你的Func函数体内没有返回结果,所以a=undefined,当然你不能给一个undefined创建属性。

  • 通过a = new Fun()调用,称之为构造函数调用。当通过new调用一个函数时发生了这几件事。
    a = new Fun()为例

    1. 构造一个空对象,假设命名为 obj = {},绑定obj__prot__Fun.prototype(涉及到js的原型链继承)

    2. 绑定函数执行环境中的this到刚才创建的空对象(即obj)上 (希望你理解了js中的this...)

    3. 执行Func函数体

    4. 如果函数体返回值是undefinednull或者不是Object类型,则返回值为最开始的obj
      所以var a = new Fun()a的值为空对象{}

  • a.name = "javascript";会直接在a上添加属性name="javascript"(这句话深究起来其实不简单..,懒得展开了,题主有兴趣多看书把。)

使用“内置对象Object”创建对象,可以不使用new,Array也可以不使用new。

最后ObjectArray可不使用new,因为他们内部做了判断,如果不是构造函数调用自动添加new.

巴扎黑

是都可以创建对象,但是new 方法创建的对象的原型是 Fun ,即a.__proto__ = Fun.protoType;而第一种是myArr.__proto__ = Object.protoType
看了一下题,发现回答有所偏差,其实可以在Fun中添加以下代码,实现安全的构造函数,达到不使用new也可创建函数:

function Fun(){
    if(!this instanceof Fun){
        return new Fun();
    }
}
左手右手慢动作

var a=Fun()表示a为函数Fun()的返回值,你Fun(){}没有返回值,a就是undefined

你试试var a = Fun(){return new Object()}呗

左手右手慢动作

我怎么记得,不用new的,那是工厂模式。

说白了就是以这个函数的返回值作为新的对象,如果你想这个函数加不加new都一样构造新的对象的话,那不想作为构造函数的其他函数怎么用呢。


    function add(a,b){
        this.sombra='boo';
        return a+b;
    }
    
    var c=add(1,2);//3
    var d= new add();//{sombra:'boo'}
伊谢尔伦

其实你要是把:

var myArr = Object();

换成

var myArr = new Object();

你不会觉得这么奇怪了,二者是相等的,只不过当你不以构造函数形式调用 Object 时,Object 等同于 new Object()(注:Array也是一样)

但这样讲反而会更迷惑,为什么呢?原因在于原型树。可这样的话,头这一定会更头大;要不就说一说为什么需要 new

我用你的示例进行思维拓展,假设你是在创建一个用户对象:

var myArr = Object();
myArr.name = "javascript";
myArr.age = 2017;

一个实例代表着一个人的姓名和年龄;我在这个基础增加了一个动作,即:zodiac() 方法来计算生肖。

那好,假如我现在需要10个用户信息,那么我需要这样:

var users = [];
for (var i = 0; i < 10; i++) {
    var myArr = new Object();
    myArr.name = "javascript";
    myArr.age = 2017;
    myArr.zodiac = function() { return this.age === 1 ? '属龙' : '属鼠'; }
    users.push(myArr);
}

看似很简单,但首先每个实例都带有 zodiac() 方法是不是太浪费内存了?每一个计算生肖的是依赖时年龄,也没有必要每一次都创建。

那好,我们可以改进一下,来解决这两个疑问。

function User() { }

// 用户生肖
function UserZodiac() {
    this.zodiac = function() {
        return this.age === 1 ? '属龙' : '属鼠';
    }
}

// 将用户的原型绑定到用户生肖
var userZodiac = new UserZodiac();
User.prototype = userZodiac;

var users = [];
for (var i = 0; i < 10; i++) {
    var myArr = new User();
    myArr.name = "javascript";
    myArr.age = 2017;
    users.push(myArr);
}

当我们创建10个用户时,只需要实例一次 UserZodiac

这才是 new 的魅力。

其实当你调用一个函数时,newnew 没有什么区别,更有一些人提倡放弃 this (相当于放弃new)。

老是有人拿原型树来考核一个人是否真懂JavaScript其实挺不合理。

阿神

Array Es文档
Object Es文档

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板