理解js中的构造函数

构造函数

构造函数用于创建特定类型的对象——不仅声明了使用的对象,构造函数还可以接受参数以便第一次创建对象的时候设置对象的成员值。你可以自定义自己的构造函数,然后在里面声明自定义类型对象的属性或方法。
特点:

  • 构造函数的首字母必须大写,用来区分于普通函数
  • 内部使用的this对象,来指向即将要生成的实例对象
  • 使用New来生成实例对象
function Person(name){
	this.name=name
	this.sayHi=function(){
		console.log(this.name+' say hi')
	}
}
var p1=new Person('小明');  //创建了两个相同参数的对象
var p2=new Person('小明')
console.log(p1.name==p2.name)   //true
console.log(p1.sayHi==p2.sayHi) //false

在这里插入图片描述
构造函数Person生成了两个对象实例p1和p2,并且都有name属性和sayHi方法。也就是说当New一个实例对象的时候,都会去创建一个sayHi方法,即引用地址不相同,所以p1.sayHi==p2.sayHi返回false,同时sayHi方法是一样的行为的,这样浪费内存资源。

根据对原型链的理解:
prototype是构造函数的属性,而consructor则是构造函数的prototype属性所指向的那个对象,也就是说constuctor是原型对象的属性。constructor属性是定义在原型对象上面,意味着也可以被实例对象继承

function Person(name){
	this.name=name
}
Person.prototype.sayHi=function(){
  console.log(this.name+' say hi')
}
var p1=new Person('小明');
var p2=new Person('小明');
console.log(p1.name==p2.name)   //true
console.log(p1.sayHi==p2.sayHi) //true

在这里插入图片描述

p1.__proto__==p2.__proto__==Person.prototype

将sayHi方法放在Person的prototype中,达到内存地址一样,实现共享。

通过实例对象(p1)的constructor(p1.constructor)访问构造函数,从而可以判断原型对象到底是哪个构造函数

console.log(p1.constructor==Person) //true
function Person(name){
	this.name=name
}
Person.prototype.sayHi=function(){
  console.log(this.name+' say hi')
}
Person.prototype.value='hi'
var p1=new Person('小明');
var p2=new Person('小明');
p1.value='hello'
console.log(p1.value)   //hello
console.log(p2.value)   //hi

有人可能有疑问了,你不是说Person.prototype里面的属性跟方法的内存地址是一样的,是共享的,为什么p1修改了value属性,p2却没有改变呢?
先忘掉前边的疑问,先来看看new 操作符干了什么

var p1 = {};
p1.__proto__ =  Person.prototype;
Person.call(p1);

第一行声明一个空对象,因为实例本身就是一个对象。
第二行将实例本身的__proto__属性指向构造函数的原型,p1新增了构造函数prototype对象上挂载的属性和方法。
第三行将构造函数的this指向替换成p1,再执行构造函数,p1新增了构造函数本地的属性和方法。

在新建后,p1,p2有了各自的this,修改实例p1的value属性,只是修改了当前对象的value的属性值,并没有影响到构造函数。所以p2中的value属性没有改变。如果想影响到其他实例应该对构造函数进行操作:

p1.__proto__.value='hello'
console.log(p2.value)   //hello
发布了20 篇原创文章 · 获赞 33 · 访问量 3250

猜你喜欢

转载自blog.csdn.net/qq_42880714/article/details/104474143