function Person(name) {
this.name = name
}
var p2 = new Person('king');
console.log(p2.__proto__) //Person.prototype
console.log(p2.__proto__.__proto__) //Object.prototype
console.log(p2.__proto__.__proto__.__proto__) // null
console.log(p2.__proto__.__proto__.__proto__.__proto__)//null后面没有了,报错
console.log(p2.__proto__.__proto__.__proto__.__proto__.__proto__)//null后面没有了,报错
console.log(p2.constructor)//Person
console.log(p2.prototype)//undefined p2是实例,没有prototype属性
console.log(Person.constructor)//Function 一个空函数
console.log(Person.prototype)//打印出Person.prototype这个对象里所有的方法和属性
console.log(Person.prototype.constructor)//Person
console.log(Person.prototype.__proto__)// Object.prototype
console.log(Person.__proto__) //Function.prototype
console.log(Function.prototype.__proto__)//Object.prototype
console.log(Function.__proto__)//Function.prototype
console.log(Object.__proto__)//Function.prototype
console.log(Object.prototype.__proto__)//null
本文重点概念:
1、所有的对象都是new一个函数创建的
2、所有的函数都有一个属性prototype,称为函数原型
3、函数原型得到的这个对象都有一个属性constructor,指向该函数
4、所有的对象都有一个属性:隐式原型__proto__,隐式原型指向创建该对象的函数的原型
5、原型链就是一直寻找__proto__,直到最终指向null
特殊:Function的隐式原型指向Function的原型
Object.prototype.__proto__ === null
1、所有的对象都是通过new一个函数创建的
var obj= {
};
这个{}是一个语法糖,本质其实就是var obj = new Object();
看一下这张图
function test() {
}
console.log(new test());//得到的是一个test对象,即构造函数是test
function test() {
return {};
}
console.log(new test());//得到的是一个Object对象,即构造函数是Object
2、所有的函数也是对象
所有的函数都是通过new一个Function来产生的,Function本身比较特殊,他是JS引擎启动时,自动就放在内存里的
函数中可以有属性
像Array.isArray这种的
3、所有的对象都是引用类型
4、所有的函数都有一个属性:prototype,称之为函数原型
比如说Object.prototype,Array.prototype
5、默认情况下,prototype是一个普通的Object对象
6、默认情况下,函数的prototype得到的这个对象,它有一个属性,constructor,他也是一个对象,他指向构造函数本身
看下面这张图
所以说Array.prototype.constructor === Array一定为真
7、 所有的对象都有一个属性:__proto__,称之为隐式原型
8、默认情况下,隐式原型指向创建该对象的函数的原型。
来个面试题
function A(){}
function B(){}
function create() {
if (Math.random() < 0.5) {
return new A();
} else {
return new B();
}
}
var obj = create();
// 如何得到创建obj的构造函数的名称
// 任何对象都有隐式原型,隐式原型指向创建它的构造函数的原型
// obj.__proto__ === A/B.prototype
// 原型里有一个constructor,表示这个原型是那个构造函数创建的
// obj.__proto__.constructor.name
看看这张图
// 共用内存空间的体现
function User(name,age){
this.name = name;
this.age = age;
this.sayHello = function(){
console.log('hello');
};//这种情况下该函数没有共用同一块内存空间 u1.sayHello === u2.sayHello false
}
User.prototype.sayHello = function(){
console.log('hello');
};//这种情况下该函数是共用的同一块内存空间 u1.__proto__.sayHello === u2.__proto__.sayHello true
var u1 = new User('a',11);
var u2 = new User('b',12);
9、 当访问一个对象的成员时
1)看该对象自身是否拥有该成员,如果有直接使用
2)看该对象的隐式原型是否拥有该成员,如果有直接使用
比如上边就可以通过u1.sayHello()直接使用
3)在原型链中,依次寻找隐式原型
10、猴子补丁:在函数原型中加入成员,以增强对象的功能,但是会造成原型污染,使用需谨慎
11、原型链
function Person(){}
var person = new Person();
console.log(person.__proto__);//Person.prototype
console.log(Person.prototype.constructor);//Person
console.log(person.constructor);//Person
console.log(Object.getPrototypeOf(person));//Person.prototype
console.log(Object.prototype.__proto__);//null