浅谈构造函数创建对象和原型链

124 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

创建对象的三种方法

字面量创建

let obj = {
    uname : name
      age :age
       sin:function(){
         concole.log('111')
    }
}

利用 对象字面量创建对象

let ojb = new Object()
obj.uname=name
obj.age=age
obj.sin=function(){
  concole.log('111')
}

利用构造函数创建对象

function Star(uname,age){
    this.uname = name
    this.age = age
    this.sing=function(){
        concole.log('111')
    }
}
let obj=new Star('张三',18)

1、其实引用类型都是对象,都是通过new创建的

2、一些内置对象的标准写法 和字面量写法 数组 : new Array() [] 对象 : new Object() {} 正则: new RegExp() //

面向过程编程

面向过程就是分析出解决问题所需要的的步骤,然后用函数把这些步骤一步一步实现,使用的时候在一个一个的依次调用就可以了

面向过程,就是按照我们分析好了的步骤,按照步骤解决问题

面向对象编程

面向对象是把事物分解成一个个对象,然后由对象之间分工与合作

面向对象是以对象功能来划分问题,而不是步骤

面向对象的特性

1、封装性 :把需要复用的代码 放入对象的方法中

2、继承性:子继承父

3、多态性:一个对象在不同情况下的多种状态

继承的三种方式

一个对象拥有另一个对象的成员(子对象继承父对象的所有成员)

混入式继承

方法:遍历父对象所有成员添加给子对象

for(let k in father){
    //遍历父对象,并将父对象的所有属性和方法添加给子对象
    son1[k]=father[k]
}
​
for(let k in father){
    //遍历父对象,并将父对象的所有属性和方法添加给子对象
    son2[k]=father[k]
}

缺点:一次只能给一个子对象继承,如果想给另一个子对象也继承必须再重复遍历父对象再添加

替换原型继承

方法:将父对象作为子对象的原型

son1.prototype=father //直接让子对象的原型等于父对象
son2.prototype=father //直接让子对象的原型等于父对象

缺点:可以实现多个子对象继承,但是会覆盖子对象原有的原型

混合式继承

方法:遍历父对象所有成员、添加给子对象的原型

for(let k in father){
    //遍历父对象,并将父对象的所有属性和方法添加给子对象的原型
    son.prototype[k]=father[k]
}

优点:可以实现多个子对象的继承,并且不会覆盖子对象原有的原型

构造函数创建对象

1、构造函数是一种特殊的函数,主要用来为对象成员变量赋初始值,与new一起用。

2、我们把对象中一些公共的属性和方法抽取出来,封装在这个函数里,然后再new一下这个函数,就创建了我们的实例对象

//构造函数
function Person(name,age){
    this.name=name
    this.age=age 
}
//原型对象
Person.prototype.eat=function(){
    console.log('1111')
}
//实例对象
let p1=new Person('张三',18)
p1.eat()

构造函数new执行过程

1、在内存中创建一个空对象

2、让this指向这个新的对象(实例对象)

3、执行构造函数里面的代码,给这个新对象添加属性和方法

4、返回这个新对象(构造函数里面不需要return)

构造函数prototype属性

每一个构造函数都会有一个prototype属性,指向另一个对象,就是prototype原型对象,这个对象的所有属性和方法,都会被配套的构造函数所拥有的

主要用法:把那些不变的方法,直接设置在prototype对象上,这样所有的实例对象都可以共享使用这些方法

构造函数的原型对象的里面设置方法:

Star.prototype.eat=function(){
      concole.log('333')
}   

只要把方法写在原型对象,所有的实例都可以使用这些方法,并且不需要重新开辟空间

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

实例对象proto属性

每个实例对象都会有一个proto属性,这个属性指向构造函数的原型对象,所以我们对象可以直接访问构造函数里原型对象的属性和方法

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

原型对象constructor 属性

原型对象里面都有一个constructor 属性,它指向的都是构造函数本身

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

可以让实例对象知道自己被哪一个构造函数创建的

构造函数、实例对象、原型对象三者之间的关系

//构造函数
function Person(name,age){
    this.name=name
    this.age=age 
}
//原型对象
Person.prototype.eat=function(){
    console.log('1111')
}
//实例对象
let p1=new Person('张三',18)
p1.eat()

image.png

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

    作用:解决资源浪费+变量污染

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

作用: 可以让实例对象访问原型中的成员 ​ 注意:proto写的时候省略

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

作用: 可以让实例对象 知道自己被哪一个构造函数创建的

原型链

image.png

原型链:每一个对象都会有自己的原型对象,原型对象也会有自己的原型,以此类推,形成的结构,称之为原型链

对象访问原型链规则:就近原则

  • 对象用属性先看自己,再看原型,再看原型的原型......一直到null,都没有就是undefined 方法报错

数组原型链

image.png

DOM对象原型链

image.png

静态成员与实例成员

1、实例对象只能访问自己的和原型对象的成员

2、 实例对象不能访问构造函数自己的成员

//构造函数
function Person(name,age){
    this.name=name
    this.age=age 
}
//原型对象
Person.prototype.eat=function(){
    console.log('1111')
}
//实例对象
let p1=new Person('张三',18)
​
​
实例成员 ——对象自己的和原型的成员
console.log(p1.name)
console.log(p1.age)
​
静态成员——构造函数自己的成员
Person.sex='男'  //这是构造函数自己的
console.log(p1.sex)//undefined   实例对象是访问不了构造函数自己的成员
console.log(Person.sex)//'男'

实例对象 只能访问自己的 和 原型成员 (实例成员)

实例对象 不可以访问构造函数中的成员 (静态成员)

\