本文重点概念:
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、原型链