原型与原型链

构造函数

基本知识

在一些典型的面向对象语言中,都存在着类的概念,类就是对象的模板,对象就是类的实例。但在js中不存在类的概念,js不是基于类,而是通过构造函数(constructor)和原型链(propotype chains)实现的。似乎在ES6中引入了类(class)的概念,作为对象的模板,由于本人对ES6的了解还不是很多,此篇不重点讲ES6中的类概念。
首先来了解一下什么是构造函数
构造函数的特点:
1、首字母大写,用于区分(约定成俗,并不是硬性要求)
2、内部使用this对象用于指向即将要生成的实例对象
3、使用New来生成实例对象
4、具有可扩展性(js中对象具有可扩展性)
eg:

function Student(name,age){
    this.name = name
    this.age = age
    this.class = '1'
    return this //默认return this 
}

var xiaoming = new Student('xiaoming',20)//实例化

看到代码其实跟传统的面向对象的编程语言其实差不多,所有的实例对象都可以继承构造函数中的属性和方法,但同一个对象实例之间是无法共享属性的,每个不同的实例有可能带有自己私有的方法或者是参数,这是通过扩展性来实现的。
当然无法共享属性也是有解决方法的,可以使用prototype,所有实例都会通过原型链引用到prototype,prototype相当于特定类型实例都可以访问到的一个公共属性,而挂到这个公共属性上面的属性以及方法,拥有这个prototype的实例就可以实现共享。

扩展

  1. var a = {}其实是var a =new Object()的语法糖
  2. var a = []其实是var a =new Array()的语法糖
  3. function Student(){} 其实是var Student = new Function(…)的语法糖
    我们在写js的时候用得更多的其实是前面的那种语法糖的写法,当然我们也更推荐前一种写法,前一种写法无论是代码的易读性还是性能上来说都比较优。

原型规则

五个原型规则

  1. 所有的引用类型(数组、对象、函数),都具有对象的特性,即可自由扩展属性(null对象除外)
  2. 所有的引用类型 (数组、对象、函数),都有一个_proto_属性,属性值是一个普通对象
  3. 所有的函数,都有一个prototype属性,属性值也是一个普通对象
  4. 所有的引用类型(数组、对象、函数),_proto_属性值指向它的构造函数的‘prototype’属性值
  5. 当试图得到对象的某个属性时,如果这个对象本身没有这个属性,那么他会去他的_proto_(即它的构造函数的prototype)中去寻找。
    前面四个原则ed:
//所有的引用类型 (数组、对象、函数),都有一个_proto_属性,属性值是一个普通对象
console.log(obj._proto_);
console.log(arr._proto_);
console.log(fn._proto_);
//所有的函数,都有一个prototype属性,属性值也是一个普通对象
console.log(fn.prototype)
//所有的引用类型(数组、对象、函数),_proto_属性值指向它的构造函数的‘prototype’属性值
console.log(obj._proto_===Object.prototype)

第五个原则可能会相对绕一点我们先看一下代码

function Student(name, age) {
    this.name = name
    this.age = age
    this.class = '1'
    return this //默认return this 
}

Student.prototype.alertName = function(){//在prototype上扩展一个函数
    alert(this.name)
}
var xiaoming = new Student('xiaoming', 20)

xiaoming.printName = function(){//扩展一个方法
    console.log(this.name)
}
//测试,两个方法都能够正确执行
xiaoming.printName()
xiaoming.alertName()

在上面的代码中,我们先是写了一个学生的构造函数,然后在这个构造函数的prototype上写了一个alertName的方法,再通过这个构造函数实例化一个学生小明并为小明扩展一个printName方法,当我们执行测试的代码的时候,第一行xiaoming.printName()很顺利地就能执行完毕,因为xiaoming这个对象里有这样的一个方法,但是当执行xiaoming.alertName的时候,xiaoming这个对象并没有这个方法,那么按照原型的第五个原则,它回去xiaoming的构造函数中去找这个名为alertName的方法,找到了就会执行,而如果还找不到那么就会继续向上,去函数的构造函数上去寻找,一直溯源到null,如果都找不到就会报错。这个原理其实就能很好地体现出什么是原型链,这里我再给出一个图:

原型链
上面这一张图很好地体现了原型链,图中方框的部分就是构造函数,圆角矩形就是对象。

instanceof

这里为什么要讲instanceof呢?instanceof是一个用于判断引用类型属于哪个构造函数的方法,这一个方法也能很好地体现原型链到底是个什么东西,因此这里放到一起讲。
xiaoming instanceof Student 的判断逻辑:
xiaoming的_proto_一层一层往上,能否对应到Student.prototype
通过这种方式能够很准确地判断出一个参数到底是什么类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值