1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 构造函数 原型对象 实例对象的关系

构造函数 原型对象 实例对象的关系

时间:2020-09-23 22:04:39

相关推荐

构造函数 原型对象 实例对象的关系

构造函数,原型对象,实例对象的关系

1.首先声明多个对象

//声明三个对象let p1={name:'张三',age:20,sex:'男}let p2={name:'李四',age:25,sex:'男'}let p3=[name:'李华'age:18,sex:'女'}

用以上方式一个个声明对象,代码过于冗余,所有我们需要用函数对他们进行封装,这样我们就引出了工厂函数

2.工厂函数:用于创建多个对象

function createPerson(name,age,sex){//1.创建对象let p = {}//2.给对象赋值p.name = namep.age = agep.sex = sex//3. 返回对象return p}let p1 = createPerson('张三',20,'男')let p2 = createPerson('李四',22,'女')console.log(p1,p2)

封装一个函数后,这样不管我们以后要创建多少个对象,都只需要传入实参调用这个工厂函数,就可以创建很多的对象,可以把它看成一个加工厂,但是我们有更加简洁的方式来实现这个功能,那就是构造函数

3.构造函数:构造函数的作用和工厂函数一致,都是用来创建对象的,但是代码更加简洁,使用new关键字调用一个函数,这个函数称为构造函数

构造函数new工作原理(4个步骤)

(1)创建一个空对象
(2)this指向这个对象
(3)给这个对象赋值
(4)返回这个对象

function Person(name,age,sex){//(1)创建空对象 {}//(2)this指向这个对象 this = {}//(3)对象赋值this.name = namethis.age = agethis.sex = sex//(4)返回这个对象 return this}let p1 = new Person('张三',20,'男')console.log(p1)

4.实例对象:用new关键字调用函数返回的对象称为实例对象

let p1 = new Person('张三',20,'男')片

这个对象是用new关键字调用函数返回的对象,称为实例对象,被调用的函数称为构造函数,

我们已经知道实例对象和构造函数,接下来说明一下什么是原型对象

5.原型对象:任何函数在声明的时候,系统都会自动帮你创建一个对象,称为原型对象

那我们为什么要使用原型对象,原型对象的作用又是什么,

首先来解决一下构造函数在使用的时候存在的问题

function Person(name,age){this.name = namethis.age = agethis.eat = function(){console.log('eat');}}let p1 = new Person('张三',18)let p2 = new Person('李四',20)console.log( p1,p2)

console.log( p1.eat == p2.eat )//false

此时p1和p2都有eat方法,而且函数体相同.但是他们是同一个函数?

答案是否定的,因为每调用一次构造函数,内部都会执行一次function,函数的数据类型是引用类型,它会在堆地址中开辟一个新的空间,虽然代码是一样的,但是地址不同,就会导致每调用一次构造函数,就会多出一个函数堆空间,导致内存资源浪费,此时我们可以使用全局函数来解决内存资源浪费问题

let eat = function() {console.log("吃东西")}let learn = function() {console.log("学习")}function Person(name, age) {this.name = namethis.age = agethis.eat = eatthis.learn = learn}let p1 = new Person("张三", 18)let p2 = new Person("李四", 20)

console.log( p1.eat == p2.eat )//true

此时p1和p2的eat方法是一样的,因为构造函数在调用的时候,构造函数内部并没有重新创建一个函数,而是拷贝eat的地址赋值,无论我们调用多少次,拷贝的都是地址,而不是在内存中重新开辟空间,这样就解决内存的浪费,但同时又会诞生一个新的问题,那就是在全局中声明太多的函数,变量名太多,可能会导致变量的全局污染,为了解决这个问题, 我们可以将这些函数加到一个新建的对象中

let obj = {eat: function() {console.log("吃东西")},learn: function() {console.log("学习")}}function Person(name, age) {this.name = namethis.age = agethis.eat = obj.eatthis.learn = obj.learn}let p1 = new Person("张三", 18)let p2 = new Person("李四", 20)console.log(p1, p2)

这样我们就可以引出原型对象,而不需要我们自己去创建一个新对象来保护变量污染

5.1原型对象的作用:解决构造函数造成的内存浪费和变量污染

//构造函数function Person(name, age) {this.name = namethis.age = age}//原型对象console.log(Person.prototype)Person.prototype = {eat: function() {console.log("吃东西")},learn: function() {console.log("学习")}}//实例对象 let p1 = new Person('张三',20)console.log( p1 )let p2 = new Person('李四',22)console.log( p1.eat == p2.eat )//truep1.eat()//p1.__proto__.eat()控制台打印吃东西console.log(Person.prototype.constructor)//Person

构造函数在声明的时候,系统会帮我们自动创建一个对象,称为原型对象,构造函数中有一个prototype指向这个原型对象,

本来构造函数里面是没有eat这个方法的,但是p1却可以调用它,这是因为构造函数的原型有这个方法,所以p1可以调用,

实例对象中有一个隐式原型__proto__指向原型对象,而原型对象中有constructor属性指向构造函数,所以我们可以总结一下三者之间的关系

原型对象相关三个属性 : 描述 构造函数、原型对象、实例对象三者关系

prototype : 属于构造函数, 指向原型对象

proto: 属于实例对象,指向原型对象

constructor : 属于原型对象,指向构造函数

验证 构造函数、原型对象、实例对象三者关系

console.log( p1.__proto__.constructor )//Personconsole.log( Person.prototype === p1.__proto__ )//true

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。