1.前置知识点
所有对象的产生都是 new Object()产生的
所有的函数也是对象,本质上都是 new Function()产生的, Function函数是JS直接放到内存中的,不是通过创建的。
函数中可以有属性
所有对象都是引用类型
2.原型 prototype
所有的函数都有一个属性:prototype,称之为函数原型
function test() {}
console.dir(test)
// 输出test的prototype
默认情况下: prototype 是一个普通的Object对象
默认情况下: prototype中有一个属性——constructor,它也是一个对象指向函数本身
Object.prototype.constructor === Object
// 结果为true
3.隐式原型 __proto__
所有的对象都有一个属性__proto__,称之为隐式原型
默认情况下:隐式原型指向创建该对象的函数的原型
当访问一个对象的成员时:
看该对象自身是否拥有该成员,如果有直接使用
看该对象的隐式原型中是否拥有该成员,如果有直接使用
在原型链中依次查找
猴子补丁:在函数原型中加入成员,以增强对象的功能,猴子补丁会导致原型污染。
function test() {}
var obj = new test()
obj.__proto__ === test.prototype
// 结果为true

小知识:每个函数有一个属性.name可以得到函数的名称
// 面试题
function A() {}
function B() {}
function create() {
if (Math.random() < 0.5) {
return A();
} else {
return B()
}
}
var obj = create();
// 如何得到创建obj的构造函数名称
console.log(obj.__proto__.constructor.name)
function User(name, age) {
this.name = name
this.age = age
this.sayHello = function() {
console.log("hello")
}
}
// sayHello可以放到原型中,被所有由User创建的对象共享
User.prototype.sayHello = function() {
console.log("hello")
}
var u1 = new User("abc", 11);
var u2 = new User("bcd", 12);
//
u1.__proto__.sayHello() // 打印hello
// 因为他们共用一块内存空间,所以打印结果为true
u2.__proto__.sayHello === u1.__proto__.sayHello
// 因为隐式原型中存在
u1.sayHello() // 也会打印hello
4.原型链

Function的__proto__指向Function自身
Object的Prototype的__proto__指向null