一、原型
js是使用构造函数来创建一个新的对象的,每一个构造函数内部都有一个prototype属性,属性值是一个对象,这个对象包含了构造函数的所有实例共享的属性和方法。
使用构造函数新建的对象内部有一个指针,指向构造函数的prototype属性对应的值,在ES5中这个指针被称作原型。
现在的浏览器实现了__proto__来访问这个属性,但是他不是规范的,ES6新增了Object.getPrototypeOf()方法获取对象的原型
二、原型链
访问一个对象属性的时候,如果没有找到就会去他原型上找,原型对象又有自己的原型,就这样一直找下去,也就是原型链的概念。
原型链的顶层是null
三、图示解释
在了解原型和原型链的关系之前,我们先梳理一下实例、构造函数、原型对象这几者存在的关系
四、构造对象的方法
// 第一种:字面量
let obj = {
name: 'tom1'
}
let obj = new Object({ name: 'tom2' })
// 第二种:构造函数
function M(name) {
this.name = name;
}
let obj = new M('tom3');
//第三种:方法
let obj = Object.create('tom4');
五、构造函数和原型对象的关系
每一个构造函数都有一个原型对象
function M(name) {
this.name = name;
}
let obj = new M('tom3');
console.log(M.prototype); // {}
原型对象通过constructor指针指向构造函数
function M(name) {
this.name = name;
}
let obj = new M('tom3');
console.log(M.prototype.constructor === M); // true
总结
涉及到构造函数和原型对象的就是:构造函数、原型对象、prototype、constructor
六、原型对象和实例的关系
实例通过内部的__proto__指向原型对象,实例和构造函数指向的是同一个原型对象
function M(name) {
this.name = name;
}
let obj = new M('tom3');
console.log(obj.__proto__);//{}
console.log(obj.__proto__ === M.prototype); // true
总结
涉及到实例和原型对象的就是:实例、原型对象、__proto__
任何一个对象都有__proto__属性,一个对象在创建之后,指针__proto__就指向了它的原型,对象的属性和方法可以从原型中继承。
实例对象可以访问原型对象的所有属性和方法
所有的实例对象共享同一个原型对象
七、构造函数和实例的关系
通过new一个构造函数得到对应的实例
// 通过new--->obj是构造函数M的实例
function M(name) {
this.name = name;
}
let obj = new M('tom3');
八、什么是原型链
解释1:
当一个对象的属性不存在时,就去他的原型上找,如果原型上也没有,就会去原型的原型上找,最后会到Object.prototype,Object.prototype的原型是null,如果没有找到返回undefined,如果在某原型处找到,返回值。这条寻找的链就是原型链。
解释2:
只要是对象就有原型,原型也是对象,因此只要定义了一个对象,就可以找到它的原型,如此反复,就可以构成一个对象序列,这就是原型链。
解释3:
由于__proto_是任何对象都有的属性,而js中一切皆对象,所以就会形成一条__proto__连起来的链条,当递归访问___proto__一定会到尽头,最终是null
九、关于Function 和Object
Function instanceof Object;//true
Object instanceof Function;//true
//因为:
Function.prototype.__proto__ === Object.prototype;//true object是顶层对象
Object.__proto__ === Function.prototype;//true
Function.__proto__ === Function.prototype; // true
- 一切对象继承Object对象,Object对象继承根对象null
- 一切函数对象(包括Object)都继承Function对象
- Object对象直接继承Function对象
- Function对象继承自己,最终继承Obejct对象
十、分析Function 和Object的关系
把Function当对象
一切对象继承Object对象,Object对象继承根对象null
例如定义let num= 1;
num的原型链: num---->Number.prototype--->Object.prototype--->null
例如定义一个let fn = function (){}
fn的原型链: fn--->Function.prototype--->Object.prototype--->null
把Object当函数
一切函数对象(包括Object)都继承Function对象
函数对象包括Function、Object、Array、String、Number,正则对象RegExp、Date对象
Function的原型链:
Function--->Funciton.prototype--->Object.prototype--->null
Object的原型链:
Obejct--->Function.prototype--->Object.prototype--->null
可以说Object和Function是互相继承的关系
object是顶层对象,Function是顶层构造函数
Function.constructor = Function
Funciton.prototype = 一个匿名函数
Funciton.prototype.__proto__ = Object.prototype
Object.conctructor = Function
Object.prototype = null
Object.__proto__ = Function.prototype
十一、prototype
每一个函数都有一个显式的属性prototype(显示原型)
var fn = function () { }
console.log(fn.prototype); // {}
十二、__proto__
每一个引用类型(数组、函数、对象)都有一个隐式的属性__proto__,(隐式原型)属性值是一个普通的值
var obj = {} // 对象
var arr = [] // 数组
var fn = function () { } // 函数
console.log(obj.__proto__); // [Object: null prototype] {}
console.log(arr.__proto__); // Object(0) []
console.log(fn.__proto__); // {}
十三、__proto__和prototype
实例对象的隐式原型__proto__指向它的构造函数的显示原型prototype
var obj = {}
var arr = []
var fn = function () { }
console.log(obj.__proto__ === Object.prototype); // true
console.log(arr.__proto__ === Array.prototype); // true
console.log(fn.__proto__ === Function.prototype); // true
十四、constructor
每一个原型(Person.prototype)都有一个constructor属性
function Person (){};
console.log(Person.prototype.constructor === Person); // true
function Person() { };
var person = new Person();
console.log(Person.prototype.constructor === Person); // true
console.log(person.__proto__.constructor === Person); // true
console.log(person.__proto__ === Person.prototype); // true
十五、原型的原型
原型也是一个对象,我们可以用最原始的方式创建它
var obj = new Object();
obj.name = 'kin';
console.log(obj.name); // kin
其实原型对象就是通过Object的构造函数生成的,实例的__proto__指向构造函数的prototype
十六、Object.prototype
Object.prototype.__proto__ === null // true
Object.prototype.__proto__ 的值为 null 跟 Object.prototype 没有原型,其实表达了一个意思。
原型链
构造函数、原型、实例之间的关系 每一个构造函数都有一个原型对象,原型对象包含指向构造函数的指针 实例包含指向原型对象的内部指针(__proto__)
如果我们让原型对象等于另一个对象的实例,此时的原型对象(Person)将包含指向另一个原型(Object)的指针(__proto__) 另一个原型对象又是另一个对象的实例,那么依然会存在上述的关系,层层递进,就会形成原型链