JavaScript构造函数和普通函数的区别

二者区别

1.调用方式

  • 普通函数直接用person()可直接调用
  • 构造函数则需要用new关键字调用,如new Person()
    (一般而言,构造函数的首字母应当大写,Person既是函数名,也是这个对象的类名)

2.this指向

  • 普通函数在非严格模式下this指向window,在严格模式下则为undefined
function person(name){
    this.name = name
    return this//普通函数要使用return
}
var p = person('Joe')
console.log(window.name === p.name) //true
  • 构造函数的this指向由该构造函数创造的实例对象
function Person(name){
    this.name = name
}
var p = new Person('Joe')
console.log(p.name) // Joe

补充:

  • 构造函数不需要return,但是它也可以用return,默认值为this,而普通函数不使用return时会返回undefined
  • 构造函数的返回值如果是基本数据类型,则依旧返回this,如果是引用类型则返回该引用类型对象
function Person(name){
    this.name = name
    return 50
}
var p1 = new Person('Joe')
console.log(p1)//Person {name: "Joe"}

function Person(name){
    this.name = name
    return ['Join','Amy','Bob']
}
var p1 = new Person('Joe')
console.log(p1)//["Join", "Amy", "Bob"]

3.构造函数的执行过程

//例如:
function Person() {
  this.name = name
}
var p1 = new Person()
  • 1.在堆中创建一份新的内存空间(p1)
  • 2.函数体内部this指向p1
  • 3.逐行执行代码
  • 4.将新创建的对象作为返回值(即this)
    这也解释了第二点中的补充为什么普通函数没有return值就会返回undefined,而构造函数却有默认值

4.由构造函数创建的实例对象可以继承构造函数中的属性,这是使用构造函数的优点之一

function Person(name){
    this.name = name
}
var p = new Person('Joe')
console.log(p instanceof Person)

构造函数的优缺点及一些补充

为什么要使用构造函数?

我们先来举个例子:当我们要创建一些拥有共同属性的对象时,要做以下操作

var p1 = { name: 'zs', age: 6, gender: '男', hobby: 'basketball' };
var p2 = { name: 'ls', age: 6, gender: '女', hobby: 'dancing' };
var p3 = { name: 'ww', age: 6, gender: '女', hobby: 'singing' };
var p4 = { name: 'zl', age: 6, gender: '男', hobby: 'football' };

这样子很麻烦,代码冗杂耦合度高
当我们使用构造函数时:

function Person(name, gender, hobby) {
    this.name = name;
    this.gender = gender;
    this.hobby = hobby;
    this.age = 6;//默认值为6
}

var p1 = new Person('zs', '男', 'basketball');
var p2 = new Person('ls', '女', 'dancing');
var p3 = new Person('ww', '女', 'singing');
var p4 = new Person('zl', '男', 'football');

只需要new一个新对象,实例对象会继承构造函数中的属性,直接传参,显然方便多了

构造函数创建的实例对象私有化

function Person(name){
    this.name = name
}
var p1 = new Person()
var p2 = new Person()
p1.name = 'Joe'
console.log(p1.name,p2.name)//Joe undefined

正是由于每创建一个新对象都会开辟一块新的内存空间,使得每个对象之间互不干扰,每个对象的属性私有化,但也因此出现了一些缺点:每创建一个新对象都创建一块内存空间导致内存的浪费,以下用原型的方法能够解决这一问题:

function Person(name){
    this.name = name
}
Person.prototype.showName = function() {
    return this.name
}
var p1 = new Person('Joe')
var p2 = new Person('Join')
console.log(p1.showName === p2.showName)//true

打印出来的结果为真,说明二者的对象方法指向了同一个函数showName

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容