构造函数
构造函数主要用来初始化对象,为对象的变量赋初始值,与new一起使用。通常把公共的属性定义到构造函数里面,公共的方法放到原型对象上。
注意:
- 构造函数用于创建某一类对象,创建时首字母大写
- 构造函数要和
new
一起使用才有意义
关于new在执行时会做的四件事在new操作符实现过程一文中已经提到。
缺点:
每创建一个实例都要开辟一个内存空间来存放同一个方法,浪费内存。
function Programmer(name,age){
this.name = name;
this.age = age;
this.job = function(){
console.log("web前端工程师");
}
}
let zsf = new Programmer("张三丰",108);
let zwj = new Programmer("张无忌",18);
创建了zsf
和zwj
两个实例后,这两个对象都需要在内存中各自开辟一个新的内存空间来存放job
方法。
而我们更希望job
方法可以被所有的实例对象共享,这样可以大大节省内存空间。构造函数原型prototype
就是来解决这个问题的。
原型是一个对象,也称prototype
为原型对象。它的作用就是共享方法,构造函数通过原型分配的函数是所有对象所共享的
Js规定,每一个构造函数都有一个prototype
属性,指向另一个对象。注意这个prototype
就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。
所以,我们可以把那些不变的方法直接定义在prototype
对象上,这样所有对象的实例就可以共享这些方法
function Programmer(name,age){
this.name = name;
this.age = age;
// this.job = function(){
// console.log("web前端工程师");
// }
}
Programmer.prototype.job = ()=>{
console.log("web前端工程师");
}
let zsf = new Programmer("张三丰",108);
let zwj = new Programmer("张无忌",18);
console.log(zsf.job === zwj.job); //true
zsf.job(); //web前端工程师
zwj.job() //web前端工程师
对象原型
对象都有一个属性__prototype
,指向构造函数的prototype
原型对象,对象之所以可以使用构造函数prototype
原型对象的属性和方法,就是因为对象有__proto__
对象原型这个属性的存在。
__proto__
对象原型和原型对象prototype
是等价的
function Programmer(name,age){
this.name = name;
this.age = age;
// this.job = function(){
// console.log("web前端工程师");
// }
}
Programmer.prototype.job = ()=>{
console.log("web前端工程师");
}
console.log(zsf); // Programmer {name: "张三丰", age: 108}
console.log(zsf.__proto__ === Programmer.prototype); //true
__proto__
对象原型的意义在于为对象的查找机制提供一个方向,是非标准属性,由于它知识内部指向原型对象prototype
,在实际开发中不可以使用这个属性。
constructor 构造函数
对象原型__proto__
和构造函数prototype
原型对象里面都有一个属性 constructor 属性 ,constructor
我们称为构造函数
constructor
主要用于记录该对象引用于那些构造函数,他可以让原型对象重新指向原来的构造函数。
通常对象的方法都在构造函数的原型对象中设置。如果有多个对象的方法,我们可以给原型对象采取对象形式赋值,但是这会覆盖构造函数原型对象原来的内容,这样修改后的原型对象constructor
就不再指向当前构造函数了。此时,我们必须手动在修改后的原型对象中,添加一个constructor
指向原来的构造函数。
function Programmer(name,age){
this.name = name;
this.age = age;
// this.job = function(){
// console.log("web前端工程师");
// }
}
Programmer.prototype = {
constructor :Programmer,
job:()=>{
console.log("web前端工程师");
},
skills:()=>{
console.log("Vue.js精通");
}
}
let zsf = new Programmer("张三丰",108);
let zwj = new Programmer("张无忌",18);
console.log(Programmer.prototype);
console.log(zsf.__proto__);
console.log(Programmer.prototype.constructor);
console.log(zsf.__proto__.constructor);
构造函数、对象实例、原型对象三者之间的关系
从上图构造函数,原型对象,对象实例三者之间的关系中,我们可以引申出原型链的概念。其基本思想就是利用对象原型__proto__让一个引用类型继承另一个引用类型的属性和方法。
有了原型链,我们就可以清晰地知道JavaScript 的成员查找机制(规则)
- 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性
- 如果没有就查找它的原型(也就是
__proto__指向的prototype原型对象
)。 - 如果还没有就查找原型对象的原型(Object的原型对象)
- 依次类推一直找到
Object
为止(null) __proto__
对象原型的意思就在于为对象成员查找机制提供一个方向。