1、构造函数是干什么用的?
在JavaScript中,构造函数是给对象添加属性,初始化属性用的。
//构造函数
function Person(name, age){
this.name = name;
this.age = age;
this.sayHi = function(){
console.log("你好");
}
}
//调用构造函数
var p = new Person("张三", 18);
var p1 = new Person("李四", 19);
console.log(p.sayHi == p1.sayHi); //输出结果为false
//原因:由于每个对象都是由new Person创建出来的,
//因此每创建一个对象,函数sayHi都会被重新创建一次,这个时候,每个对象都拥有一个独立的,但是功能完全相同的方法。
功能相同的函数,完全没有必要再内存中存在这么多份。所以就造成了资源浪费。
- 解决:这里最好的办法就是将函数体放在构造函数之外. 在构造函数中只需要引用该函数即可。
function sayHello(){
console.log("你好");
}
function Person(name, age){
this.name = name;
this.age = age;
this.sayHi = sayHello;
}
//调用该构造函数创建对象,并对比创建出来的对象的sayHi方法
var p = new Person("张三", 18);
var p1 = new Person("李四", 19);
console.log(p.sayHi == p1.sayHi); //输出结果为true
- 存在问题:全局变量增多,会增加引入框架命名冲突的风险代码结构混乱,会变得难以维护
最终解决:-----利用原型
关键点
每一个函数在定义的时候,都会有跟它关联的一个对象被创建出来
每一个由构造函数创建出来的对象,都会默认的和构造函数的神秘对象关联
当使用一个方法进行属性或者方法访问的时候,会先在当前对象内查找该属性和方法
如果当前对象内未找到,就回去跟它关联的神秘对象内进行查找
//可以通过 构造函数.prototype 访问这个神秘对象
console.log(Person.prototype);
*当尝试给这个对象新增一个方法之后:
Person.prototype.sayHello = function(){
console.log(“我是神秘对象中的方法”);
};
使用p,p1都可以访问这个方法:
p.sayHello();
p1.sayHello();
总结:
所有对象共享神秘对象(构造函数.prototype)内的属性和方法。
解决方案
既然所有对象共享神秘对象(构造函数.prototype)内的属性和方法。我们只需要将需要共享的东西,也就是重复占用内存的东西,全部都放到 神秘对象(构造函数.prototype)中,那么所有对象就都可以使用,并且内存里面也只有一份了
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayHi = function(){
console.log("你好");
};
//测试
var p = new Person("张三", 18);
var p1 = new Person("李四", 19);
console.log(p.sayHi == p1.sayHi); //输出true
常见的错误
- 将属性写在神秘对象(构造函数.prototype)内
function Car(name){
this.name = name;
}
function Person() {}
Person.prototype.name = '张三'; //基本类型的属性影响不大
Person.prototype.car = new Car("法拉利"); //引用类型的属性,会被所有的对象共享
var p = new Person();
- 赋值的错误
function Person() {}
Person.prototype.name = '张三';
var p1 = new Person();
var p2 = new Person();
p1.name = '李四';
console.log( p1.name );
console.log( p2.name );
// 如果是访问数据, 当前对象中如果没有该数据就到构造函数的原型属性中去找
// 如果是写数据, 当对象中有该数据的时候, 就是修改值; 如果对象没有该数据, 那么就添加值