用new和不用new调用构造函数,有什么区别

本文探讨了在JavaScript中使用new关键字与不使用new关键字调用构造函数的区别。主要从构造函数的执行环境、返回值类型及作用域等方面进行详细解析。

用new和不用new调用构造函数,有什么区别

一、没有return

        function Person(name) {
            this.name = name;
            console.log(this.name);
        }
        var a = Person('Tom'); // Tom 
        var b = new Person('LI') // LI
        console.log(a) // undefined
        console.log(b) // Person {name: "LI"}

1.不使用newthis对象指向window,并且,不会默认返回任何对象
2.使用newthis对象指向的是Person 实例

二、有return
1.简单数据类型:数值,字符串、布尔值、null、undefined

        function Person(name) {
            this.name = name;
            console.log(this.name);
            return 1
        }
        var a = Person('Tom') // Tom
        var b = new Person('LI') // LI 
        console.log(a) // 1
        console.log(b) // Person {name: "LI"} 
        console.log(a.name) // undefined
        console.log(b.name) // LI

2.复杂数据类型:对象即属性的集合(function、Array、Object)

        function Person(name) {
            this.name = name;
            console.log(this.name);
            return [1,2,3]
        }
        var a = Person('Tom') // Tom
        var b = new Person('LI') // LI 
        console.log(a) // [1,2,3]
        console.log(b) // [1,2,3]
        console.log(a.name) // undefined
        console.log(b.name) // undefined

(1)不使用newreturn之后,得到的就是return的返回值
(2)使用newreturn之后,就会出现两种情况,一种是返回的是简 单数据类型,这时返回值会被自动忽略,返回的还是原来的实例。另一种是返回的是复杂数据类型,此时得到的就是return的返回对象。

### ### JavaScript调用构造函数的其他方法 在 JavaScript 中,构造函数本质上仍然是普通函数,与普通函数唯一的区别在于调用方式。虽然通常使用 `new` 关键字来调用构造函数以创建对象实例,但也可以通过其他方式模拟构造函数的行为,甚至在不使用 `new` 的情况下实现类似的效果。 #### 使用 `call` 或 `apply` 方法 构造函数可以像普通函数一样被调用,但此时 `this` 会指向全局对象(如 `window` 或 `global`)。为了在特定上下文中调用构造函数并模拟实例化行为,可以使用 `Function.prototype.call` 或 `Function.prototype.apply` 方法。例如: ```javascript function Person(name, age) { this.name = name; this.age = age; } const person = {}; Person.call(person, 'Alice', 25); ``` 上述代码中,`Person` 函数被当作普通函数调用,但通过 `call` 指定了 `this` 的值为 `person` 对象,从而将属性绑定到该对象上[^2]。 #### 使用工厂函数模式 工厂函数是一种设计模式,它通过封装对象的创建过程来返回对象实例。这种方式不依赖于 `new`,但可以模拟构造函数的功能: ```javascript function createPerson(name, age) { const obj = {}; obj.name = name; obj.age = age; return obj; } const person = createPerson('Bob', 30); ``` 工厂函数返回一个新创建的对象,其行为与构造函数类似,但不需要使用 `new` 关键字[^3]。 #### 使用 `new.target` 属性判断调用方式 ES6 引入了 `new.target` 属性,用于检测函数是否通过 `new` 调用。可以在构造函数内部使用该属性来确保函数只能通过 `new` 调用,或者在未使用 `new` 时自动补救: ```javascript function Person(name, age) { if (!new.target) { return new Person(name, age); } this.name = name; this.age = age; } const person1 = new Person('Charlie', 35); const person2 = Person('Diana', 28); // 自动补救为 new 调用 ``` 此方法可以在不使用 `new` 的情况下自动返回构造函数的实例,从而避免错误调用导致的全局对象污染[^3]。 #### 使用类(Class)语法(ES6+) 虽然类本质上仍然使用构造函数机制,但 ES6 引入的类语法提供了一种更清晰的面向对象编程方式: ```javascript class Person { constructor(name, age) { this.name = name; this.age = age; } } const person = new Person('Eve', 40); ``` 类的构造函数必须通过 `new` 调用,否则会抛出错误。因此,类语法并未提供替代 `new` 的方式,但封装了构造逻辑,使代码更易维护[^4]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值