# 原型与原型链 `JavaScript`有着七种基本类型`String`、`Number`、`Boolean`、`Null`、`Undefined`、`Symbol`、`Object`,前六种为基本数据类型,`Object`为引用类型。函数本质上是`Object`类型,也就是一个对象。 > 值得注意的是`typeof (null)`会返回`Object`,这是因为`JS`二进制前三位都为`0`的话会被判断为`Object`类型,`null`的二进制表示是全`0`,自然前三位也是`0`,所以执行`typeof`时会返回`Object`,实际`null`为基本数据类型。 ## 构造函数对象 构造一个`Student`类,实例化`Student`出`stu`实例对象。 ```javascript function Student() {} var stu = new Student(); stu.name = "Ming"; console.log(stu.name) // Ming ``` ## prototype 每个函数对象都会有一个`prototype`属性,`prototype`就是调用构造函数所创建的那个实例对象的原型,`prototype`可以让所有对象实例共享它所包含的属性和方法。 ```javascript function Student() {} Student.prototype = { from: "sdust" } var stu1 = new Student(); var stu2 = new Student(); console.log(stu1.from) // sdust console.log(stu2.from) // sdust ``` ## \_\_proto\_\_ `__proto__ `是原型链查询中实际用到的,它总是指向`prototype`,就是指向构造函数`Student`的原型对象`prototype`。例如实例化的`stu`会使用`__proto__`向`Student`的`prototype`寻找方法或属性。若`stu`寻找到了调用的方法或属性,则不会使用`__proto__`寻找原型对象。 ```javascript function Student() {} Student.prototype = { from: "sdust" } var stu = new Student(); console.log(stu.__proto__ === Student.prototype) // true console.log(stu.from) // sdust stu.from = "s"; console.log(stu.from) // s ``` ## constructor 每个原型都有一个`constructor`属性指向关联的构造函数`Student`,实例的`constructor`指向构造函数`Student`。 ```javascript function Student() {} var stu = new Student(); console.log(Student.prototype.constructor === Student) // true console.log(stu.constructor === Student) // true ``` ## 原型链 原型链可以简单理解为将原型连成一条链,`js`每一次获取对象中的属性都是一次查询过程,如果在自有属性中找不到就会去原型对象中查找,如果原型对象中还查不到,就回去原型对象的原型中查找,也就是按照原型链查找,直到查找到原型链的顶端,也就是`Object`的原型。 ```javascript function parent() { this.parentInfo = "parent"; } parent.prototype.getParentInfo = function() { return this.parentInfo; }; function child(){ this.childInfo = "child"; } parent.prototype.getChildInfo = function() { return this.childInfo; }; child.prototype = new parent(); var instance = new child(); console.log(instance.getChildInfo()); // child console.log(instance.getParentInfo()); // parent console.log(instance.parentInfo); // parent console.log(instance.__proto__ === child.prototype); //true console.log(instance.__proto__.__proto__ === parent.prototype); //true console.log(instance.__proto__.__proto__.__proto__ === Object.prototype); //true console.log(instance.__proto__.__proto__.__proto__.__proto__ === null); //true // function student(){} // console.log(student.__proto__ === Function.prototype) // true // console.log(Function.__proto__ === Function.prototype) // true // console.log(Object.__proto__ === Function.prototype) // true // console.log(Object.prototype.__proto__ === null) // true ``` ## 每日一题 ``` https://github.com/WindrunnerMax/EveryDay ```