原型链
一、概念
构造函数的prototype里面的__proto__属性指向哪里?
对象的__proto__和对象的构造函数原型是同一个对象
一个对象所属的构造函数:
// 数组
const arr = [1,2,3];
console.log(arr.constructor); // Array
// 函数
const fn = function(){};
console.log(fn.constructor); // Function
// 对象
const obj = {};
console.log(obj.constructor); // Object
// 正则
const reg = /abc/
console.log(reg.constructor); // RegExp
每一个对象的__proto__上面都有一个自带属性:constructor,就是这个对象的构造函数
当一个对象不知道准确是谁构造的,就把它当做Object构造的实例对象
Object是顶级构造对象
function Human(){}
console.log(Human.prototype);// 找到Human对象的构造函数
console.log(Human.prototype.constructor);// Human(){} 因为函数本身有内容,所以找到了自身
console.log(Human.prototype.__proto__.constructor)// Object(){} 指定去原型里面找,证明了Human这个对象是Object构造的实例对象
二、链式结构
对象的__proto__指向其构造函数的原型prototype
以一个实例对象为起点,沿着__proto__形成的链条,就是原型链
在原型链的末尾是Object.prototype, Object.prototype.__proto__就是null
原型链的访问原则:
访问一个对象的属性时,如果自己没有就去 __proto__ 上找,
如果__proto__有就返回结果,如果没有就继续去__proto__上找,
一直找到Object.prototype里面都没有,就返回undefined.
const h2 = new Human();
/*
h2 = {
name:'lucy',
__proto__ = Human.prototype ={
sayHi:function(){},
__proto__ = Object.prototype = {
toString:function(){},
__proto__:null
}
}
}
==> 代表沿着__proto__
h2 ==> Human.prototype ==> Object.prototype ==> null
*/
const arr = [12,34,56];
/*
arr = {
0:12,
1:34,
2:56,
length:3,
__proto__:Array.prototype = {
push:function(){},
__proto__:Object.prototype = {
toString:function(){},
__proto__:null
}
}
}
==> 代表沿着__proto__
arr => Array.prototype ==> Object.prototype ==> null
测试发现下方的链,这是现代新版浏览器的解析结果,后面都是重复的,在编程思想上,只需要理解上方的原型链即可。
arr => Array.prototype ==> Object.prototype ==> Array.prototype ==> Object.prototype ==> Object.prototype ==> null
*/
面试题:如何精确判断数据类型?
提示:如何调用Object.prototype上的toString方法?
ES6的类语法
es6新增一个class语法,用于书写类(等价于es5语法中的构造函数)
语法:class 类名{constructor(){给对象添加属性} 给对象添加方法}
class Person(){
constructor(name,age){
this.name = name;
this.age = age;
}
// 给对象添加方法,就是添加在构造函数的原型上
sayHi(){
console.log('hi');
}
sayName(){
// 原型方法中的this是实例对象
console.log(this.name);
}
}
// 实例对象
const p1 = new Person('lucy',12);
console.log(p1);
/*
p1 = {
name = 'lucy',
age = 12,
__proto__:{
sayHi(){},
sayName(){},
}
}
*/