构造函数和原型

151 阅读4分钟

构造函数

含义:

构造函数是一种特殊的函数,用来初始化对象,为对象成员变量赋初始值,与 new 一起使用。可以吧对象中的一些公共属性和方法抽取出来,然后封装到这个函数里面

new 在执行的时候做的四件事情

  1. 在内存中创建一个新的空对象
  2. 让this指向这个新的对象
  3. 执行构造函数里面的代码,给这个新对象添加属性和方法
  4. 返回这个新对象(所以构造函数里不需要return

构造函数的缺点

创建对象时,里面的方法(function是复杂数据类型)会在内存中重新开辟空间,也就是每一个实例对象都会开辟一块空间,存在浪费内存的问题。

代码示例
/*构造函数*/
function Person(sName,sPhone){
	this.name=sName
	this.phone=sPhone
	this.run=function(){
	console.log('奔跑');
}
}
			
// 实例化创建新的原型对象,新的原型对象会共享原型的属性和方法
 const p1 = new Person("张三", "15623233232");
 const p2 = new Person("李四", "17789899898");
			
console.log(p1.run===p2.run);//false,代表地址不同

通过构造函数创建的新对象实例是相互独立的,为新对象实例添加的方法只有该实例拥有这个方法,其它实例是没有这个方法的

/*构造函数*/
function Person(sName,sPhone){
	this.name=sName
	this.phone=sPhone
	this.run=function(){
	console.log('奔跑');
}
}
			
// 实例化创建新的原型对象,新的原型对象会共享原型的属性和方法
const p1 = new Person("张三", "15623233232");
const p2 = new Person("李四", "17789899898");
 // 为新对象实例添加方法
// 通过原型创建的新对象实例是相互独立的
p1.sayHello = function(){
  console.log("你好啊");
}
p1.sayHello() //你好啊
p2.sayHello() //报错

构造函数原型 prototype (显式原型)

1.函数才有prototype,prototype是一个对象,指向了当前构造函数的引用地址 2.这个原型对象 prototype 的所有属性和方法都会被构造函数所拥有。 3.我们可以把公共的方法,直接定义在 prototype 对象上, 这样所有对象的实例就可以共享这个方法了

代码示例
/*构造函数原型 prototype*/
function Person(sName,sPhone){
	this.name=sName
	this.phone=sPhone
	this.run=function(){
	console.log('奔跑');
 }
}
Person.prototype.run=function(){
 console.log('奔跑');
}
 // 实例化创建新的原型对象,新的原型对象会共享原型的属性和方法
const p1 = new Person("张三", "15623233232");
const p2 = new Person("李四", "17789899898");
console.log(p1.run===p2.run);//true,代表地址相同

对象原型 _proto_(隐式原型)

1.对象都有一个属性__proto__指向构造函数的 prototype 原型对象 2.之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有__proto__原型的存在 3.__proto__对象原型和原型对象 prototype 是等价的

代码示例
 console.log(p1.__proto__ === Person.prototype); //true

原型 constructor

原型 里有 constructor 这个属性,主要作用是告诉我们是由那个构造函数中创建出来的 如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数。 因为新添加的对象覆盖了原来构造函数的prototype对象

  function Person(sName,sPhone){
	this.name=sName
	this.phone=sPhone
	this.run=function(){
	console.log('奔跑');
}
}
Person.prototype = {
  constructor: Person,
  run: function () {
   console.log("奔跑");
},
  eat: function () {
    console.log("吃东西");
   },
};
      // 实例化创建新的原型对象,新的原型对象会共享原型的属性和方法
const p1 = new Person("张三", "15623233232");
const p2 = new Person("李四", "17789899898");
console.log(Person.prototype);
console.log(p1.__proto__);
查找规则(原型链)

首先看p1对象身上是否存在 run 方法,如果有就执行这个对象身上的 run ,如果没有,因为有__proto__的存在,就去构造函数原型对象prototype身上去查找这个 run 方法。 这样一层一层向上查找就会形成一个链式结构 在这里插入图片描述

检查对象自身是否含有某个属性的方法

1.hasOwnProperty

 let obj = {
    a: 5,
    b: 10,
  };
	
console.log("21", obj.hasOwnProperty("a"));

2 in

console.log('a' in obj)

prototype 和 proto 区别是什么?

  1. prototype是构造函数的属性
  2. __proto__是每个实例都有的属性,可以访问 [[prototype]] 属性
  3. 实例的__proto__与其构造函数的prototype指向的是同一个对象