这块需要大家先自行了解一下什么原型对象,为什么需要原型对象,怎么访问,这里就不展开说了
1. 先抛出一个场景
function Fn(){
}
let f = new Fn()
console.log(f.toString())
//则会返回[object object]
上面,我并没有定义 这个 toString() 方法为什么还是生效?
答案:是因为这个方法存在 Object 对象中的原型中,f 通过原型链找到了这个方法
2. 首先介绍一下什么是原型链
每一个对象都有原型,原型本身又是对象,所以原型又有原型,以此类推形成一个链式结构,称为原型链(原型链的终点是null)
先浅浅抛出一张图
3. 原型链的访问规则
当访问一个对象的成员变量时,会首先访问它自身的成员变量,如果有则访问。没有则在原型中寻找,能找到就访问,不能找到则继续往原型的原型中寻找,以此类推,如果找到原型链的顶端还是找不到,则程序报错:xxx is not a function
说明一下报错的原因,执行p1.learn(),p1找不到learn方法会报undefined的错误,然后加上小括号调用函数,所以会报不是function的错误
4. 注意点
原型对象 : 常用来存储具有共同特征的数据(多个不同的实例对象可以调用)
Person.prototype.type = '哺乳动物'
Person.prototype.country = '中国'
Person.prototype.eat = function(){
console.log(this.name + '吃东西')
}
p1.toString,p1自己没有toString, p1的原型也没有toString, 但是为什么不报错呢?
原因: p1的原型的原型有toString
//查看p1的原型
console.log( p1.__proto__.constructor )//Person
console.log( Person.prototype === p1.__proto__ )//true
//查看p1的原型的原型
console.log( p1.__proto__.__proto__.constructor )//Object
console.log( Object.prototype === p1.__proto__.__proto__ )//true
//查看p1的原型的原型的原型
console.log( p1.__proto__.__proto__.__proto__ )//null
注意点:
- 所有的对象的原型都最终指向内置构造函数Object的原型对象,再最终指向null
- 构造函数本身也是一个对象,也是由构造函数创建的,也有自己的原型链(作用不大,仅作了解)
- 只要是对象就有原型,原型对象是由内置构造函数Object创建的
5. 思考
为什么 arr.toString() 方法和对象的 toString() 方法得到的结果不同
回答:数组的原型含有 toString 方法用来转换成字符串,对象的 toString 方法是 Object 的原型里面的方法,是专门用来监测数据类型的
let arr=[1,2,3,4]
console.log(arr.toString())
//则会返回1,2,3,4
function Fn(){
}
let f = new Fn()
console.log(f.toString())
//则会返回[object object]