一、构造函数补充
现在我们的方法直接定义在了构造函数中,也就是构造函数,每执行一次,就会创建一个新的函数对象,
这样也就意味着,每一个对象都有不同的sayHello()方法,但是这些sayHello()的功能却是一样的,而创建许多会占用大量的内存空间,实际上完全可以所有的对象都公用一个sayHello()
// 定义一个表示人的类
function Person(name, age) {
this.name = name;
this.age = age;
// // 向类中添加一个方法
// this.sayHello = function () {
// alert(`大家好,我是${this.name}`)
// };
// 修改
this.sayHello = sayHello;
}
//修改:将 sayHello()定义为一个全局函数
// 但会污染全局的命名空间(namespace)
function sayHello() {
alert(`大家好,我是${this.name}`)
};
// 创建一个人类的实例
let per1 = new Person('孙悟空', 18);
let per2 = new Person('猪八戒', 28);
per1.sayHello();
per2.sayHello();
console.log(per1.sayHello === per2.sayHello);//false,实际是有两个sayHello,修改后就为true,调用的是同一方法
二、原型简介
每个函数对象中都有一个属性叫做prototype,该属性指向的是一个对象,这个对象叫原型对象。
如果函数作为普通函数调用,则原型对象(prototype)没有任何作用;
如果函数作为构造函数调用(let xxx= new 函数()),那么通过该构造函数的所创建的对象中,都会有一个隐含的属性(proto)指向函数的原型对象(prototype);也就是说,该类的所有实例中都会有一个隐含属性指向构造函数的prototype,原型对象就相当于一个公共的区域可以被所有的该类实例访问,可以将一些实例共有的属性或方法存储在原型对象中,这样只需要设置一次即可让所有的对象都访问到该属性;当我们访问一个对象中的属性时,js会先在对象本身中寻找,如果找到了则直接使用,如果没有找到则去对象的原型(proto)中寻找,找到了则使用;
结论:
定义一个类时,如果属性和方法是对象独有的,就直接在构造函数中设置
function 类名(){
this.xxx=yyy;
}
如果属性和方法是公共的,每一个对象的值都是相同,可以通过原型(proto)来添加,类.prototype.属性名=值(也可以是个函数);
function Myclass() {
}
// 向原型中添加一个属性
Myclass.prototype.name = '原型中的name属性';
let mc = new Myclass();
let mc2 = new Myclass();
mc.name = '孙悟空';
// 访问mc中的隐含属性
console.log('-----', mc.__proto__);//Object
console.log(Myclass.prototype);//Object
console.log(mc.__proto__ === Myclass.prototype);//true
console.log(mc2.__proto__ === Myclass.prototype);//true
console.log(mc.name);//孙悟空
console.log(mc2.name);//原型中的name属性
函数补充的完美解决方法
// 定义一个表示人的类
function Person(name, age) {
this.name = name;
this.age = age;
}
// 不会重复创建,利用原型(prototype)
Person.prototype.sayHello = function () {
alert(`大家好,我是${this.name}`);
};
// 创建一个人类的实例
let per1 = new Person('孙悟空', 18);
let per2 = new Person('猪八戒', 28);
per1.sayHello();//调用原型的方法
per2.sayHello();
console.log(per1.sayHello === per2.sayHello);//false,实际是有两个sayHello,修改后就为true,调用的是同一方法