二者区别
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