构造函数

  • 构造函数语法:大写字母开头的函数
  • 创建构造函数

实例成员&静态成员

实例成员

通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员。

//构造函数
function person(){
//构造函数内部的 this 就是实例对象
//实例对象中动态添加属性
this.name = '坤坤'
//实例对象动态添加方法
this.sayHi = function (){
console.log('鸡你太美')
}
}
实例化 ikun 是实例对象 也就是构造函数的this
const ikun = new person()
console.log('ikun.name') //访问实例属性
ikun.sayHi() //调用实例方法

说明

  • 实例对象的属性和方法即为实例成员
  • 为构造函数传入参数,动态创建结构相同但值不同的对象
  • 构造函数创建的实例对象彼此独立互不影响。

静态成员

构造函数的属性和方法被称为静态成员

//构造函数
function Person (name,age){
this.name=name
}
//静态属性
Person.eyes = 2
Person.hand = 1
//静态方法
Person.walk = function(){
console.log('坤坤会鸡叫')
this 指向 person
console.log('this.eyes')
}

说明

  • 构造函数的属性和方法被称为静态成员
  • 一般公共特征的属性或方法静态成员设置为静态成员
  • 静态成员方法中的 this 指向构造函数本身

内置构造函数

Object

  • Object 是内置的构造函数,用于创建普通对象。

  • 常用的三个静态方法(静态方法就是只有构造函数Object可以调用的)

Object.keys() // 获取对象所有的键,返回一个数组

Object.values() // 获取对象所有的值,返回一个数组

Object.assign() //拷贝对象

Object.keys() 静态方法获取对象中所有属性(键)

const o ={name : '坤坤',age : 18}
获得对象的所有键,并且返回是一个数组
const arr = Object.keys(o)
console.log(arr) // ['name','age']

注意:返回的是一个数组

Object.values 静态方法获取对象中所有属性值

const o ={name : '坤坤',age : 18}
获得对象的所有键,并且返回是一个数组
const arr = Object.values(o)
console.log(arr) // ['坤坤','18']

注意:返回的是一个数组

Object. assign 静态方法常用于对象拷贝

// 给 o 新增属性
const o ={name : '坤坤',age : 18}
Object.assign(o,{gender:'女'})
console.log(o) // {name:'佩奇',age:6,gender:'女'}

Array String Number的方法这里就不写了,需要可以去看文档 MDNopen in new window

编程思想

面向过程编程

  • 优点:性能比面向对象高,适合跟硬件联系很紧密的东西,例如单片机就采用的面向过程编程。
  • 缺点:没有面向对象易维护、易复用、易扩展

面向对象编程

  • 优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护
  • 缺点:性能比面向过程低

总结:生活离不开蛋炒饭,也离不开盖浇饭,选择不同而已,只不过前端不同于其他语言,面向过程更多

原型

  • 构造函数通过原型分配的函数是所有对象所 共享的。
  • JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象
  • 这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存
  • 我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法
function Star(uname,age){
this.uname = uname
this.age = age
}
console.log(Star.prototype) //返回一个对象称为原型对象
将方法挂载到原型上,该构造函数的实例对象都能访问到
Star.prototype.sing =function(){
console.log('我会唱歌')
}
const ldh = new Star('刘德华',18)
const zxy = new Star('张学友',19)
console.log(ldh.sing===zxy.sing)
//结果true 说明实例对象调用的是同一个方法不会造成内存浪费

constructor属性

每个原型对象里面都有个constructor 属性,该属性指向该原型对象的构造函数

使用场景

  • 如果有多个对象的方法,我们可以给原型对象采取对象形式赋值.
  • 但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor 就不再指向当前构造函数了
  • 此时,我们可以在修改后的原型对象中,添加一个 constructor 指向原来的构造函数。
function Star(name){
this.name = name
}
Star.prototype = {
手动让修改后的原型对象利用 constructor 重新指向star构造函数
constructor:Star
sing: function (){console.log('唱歌')}
}
console.log(Star.prototype.constructor) //指向Star

对象原型

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

原型继承

继承是面向对象编程的另一个特征,通过继承进一步提升代码封装的程度,JavaScript 中大多是借助原型对象实现继承 的特性。

 // 实例共同的父亲必须是构造函数因为console.log(p1===p2) 结果为false
//这样的话 man和woman两个子构造函数就不会互相造成影响了
function Person(){
   this.eays=2,
   this.head=1
 }
const p1 = new Person()
const p2 = new Person()
function Man(){
}
Man.prototype=new Person()
// 通过赋值让构造函数的原型对象指向 person这个对象 但这个对象里面没有countrutor
const pink = new Man()
Man.prototype.countructor = Man //让构造函数的原型对象的countructor指回 构造函数
Man.prototype.baby=function(){
   console.log('hollw')
}
console.log(pink)
console.log(Man.prototype.countructor)
console.log(Man.prototype)
pink.baby()
function Woman(){
}
Woman.prototype=new Person()
Woman.prototype.countructor=Woman
const red = new Woman()
console.log(red)

原型链

基于原型对象的继承使得不同构造函数的原型对象关联在一起,并且这种关联的关系是一种链状的结构,我们将原型对象的链状结构关系称为原型链

原型链-查找规则

  • ① 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。
  • ② 如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)
  • ③ 如果还没有就查找原型对象的原型(Object的原型对象)
  • ④ 依此类推一直找到 Object 为止(null)
  • ⑤ __proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线