原型链、隐式原型之间的关系你搞懂了吗?
听说面试要被考到?
原型和原型链
你们知道所有的对象都是通过new函数
创建的吗?
var obj = new Object(); var obj = {}
这里的var obj={},大括号是语法糖 相当于new Object={};
就比如:
function test(){
return {}
}
new test();
--------这里是有产生对象的,并且这里的构造函数是Object对象,因为return返回的是一个{} 相当于return new Object;
所有的函数也是对象
Function函数也是一个对象,但是所有的对象都是通过new来创建的,所以Function是放在内存中的,js引擎启动的时候直接把Function放在内存中。
typeof Object
-----“function”
typeof Array
----“function”
函数里面可以有属性
Array.isArray();
所有对象都是引用类型(—保存的是地址 ,赋值的也是地址)
什么是原型?
JS中的对象包含了一个prototype的内部属性,这个属性所对应的就是该对象的原型。
我们先看下图:a、b、c 分别为数组、对象、函数。
var a =[1,2,3]
var b = {
color:‘red’,
size:‘12’
}
function c(){
alert(‘c’)
}
可以看到,三者都有一个属性:__proto__
这个 __proto__
称作 隐式原型。
除此之外,c还有一个属性:prototype
这个prototype 称作 显式原型。
原型 prototype
所有函数都有一个属性:prototype,称之为函数原型
只要是函数都有原型
默认情况下,prototype是一个普通的Object对象
默认情况下,prototype中有一个属性,constructor,它也是一个对象,他指向构造函数本身。
这里强调的是默认情况下
test.prototype.constructor === test返回的是true
隐式原型 __proto__
(两个下划线开头的一般都是系统变量,不要轻易改变)
(1)所有的对象都有一个属性:__proto__
,称之为隐式原型
(2)在原型链中依次查找是否拥有该成员,如果有直接使用
({}).__proto__
var obj = {};
obj.prototype;----undefined
obj是一个普通对象,不是函数,就没有prototype,普通对象是有__proto__的
obj.__proto__ ={constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
因为prototype也是一个对象,所以prototype也有__proto__
当访问一个对象的成员时:
- 看该对象自身是否拥有该成员,如果有直接使用
- 在原型链中依次查找是否拥有该成员,如果有直接使用
猴子补丁:在函数原型中加入成员,以增强起对象的功能,
猴子补丁会导致原型污染,使用需谨慎。
function test1() {
return {};//这里就相当于new Object()
}
var obj = new test1();
console.log(obj.__proto__ === test1.prototype); //输出false
function test2() {
}
var obj = new test2();
console.log(obj.__proto__ === test2.prototype); //输出true
所有的函数都是通过new Function来产生的
特殊点:
1.Function的__proto__指向自身的prototype
2.Object的prototype的__proto__指向null
function User(){}
User.prototype.sayHello = function(){}
const u3 = new User();
const u4 = new User();
console.log(u3.sayHello === u4.sayHello);//true
console.log(User.prototype.constructor);//User
console.log(User.prototype === Function.prototype);//false
console.log(User.__proto__ === Function.prototype );//true
console.log(User.__proto__ === Function.__proto__);//true
console.log(u3.__proto__ === u4.__proto__);//true
console.log(u3.__proto__ === User.__proto__ );//false
console.log(Function.__proto__===Object.__proto__);//true
console.log(Function.prototype.__proto__ === Object.prototype.__proto__);//false
console.log(Function.prototype.__proto__ === Object.prototype);//true
以上的代码照着上面的图做就可以做出来,以后做题就可以在脑海了会议这个图就很容易的写出来,面试的时候还会怕被问到原型和原型链吗?
小结一下:
所有引用类型(函数,数组,对象)都拥有__proto__属性(隐式原型)
所有函数除了有_proto_属性之外还拥有prototype属性(显式原型)
原型对象:每创建一个函数,该函数会自动带有一个prototype属性,该属性是一个指针,指向了一个对象,我们称之为原型对象。
总结如下:
- 实例对象a只有__proto__(隐式原型),构造函数既有 proto(隐式原型)也有prototype(显式原型)
- proto 和 prototype 都是一个对象,既然是对象,就表示他们也有一个 proto
var F = function () {}
Object.prototype.a = function () {}
Function.prototype.b = function () {}
var f = new F();
console.log(f.a, f.b, F.a, F.b);
// fn undefined fn fn
// 看图,所有的Function原型都指向Object原型,所以所有对象的原型上都有a
//所有的函数都有b方法了,F是函数,f是通过函数创建的对象
function A() {}
A.prototype.toString = function() {
return "123";
}
var obj = new A();