原型
(1) 显式原型 prototype:每个函数function都有一个prototype,即显式原型(属性);指向原型对象.
// prototype是函数才会有的属性
(2) 隐式原型_proto_:每个实例对象都有一个_proto_,称为隐式原型(属性);事实上就是原型链指针
(3) 对象的隐式原型属性的值=对应构造函数的显示原型属性的值;
实例._proto_=func.prototype
(4)constructor: 每一个原型对象都包含一个指向构造函数的指针,就是constructor。
原型对象中有一个constructor属性,指向函数对象(本身);
function Fun{};
//默认指向一个空的Object对象
console.log(Fun.prototype); //
console.log(Fun.prototype.constructor === Fun) //true
总结:
- 函数的prototype:是定义函数时自动添加的,默认是一个空的Object对象;
- 实例对象的_proto_属性:创建对象的时候自动添加的,默认为构造函数的prototype属性值。
例:
function Fun{};
//默认指向一个空的Object对象
console.log(Fun.prototype); //对应(1)
var fn = new Fun();
console.log(fn._proto) //对应(2)
console.log(fn._proto==Fun.prototype) //true 对应(3)
原型链:用来查找对象属性或者方法。
访问一个对象的属性时:
-
先在自身属性中查找,找到返回。
-
若没有,则沿着_proto_这条链向上查找,找到返回。
-
若最终查找到Object.prototype都没有找到, 返回undefined。
继承实现方式:
为了实现继承,proto会指向上一层的原型对象,而上一层的结构依然类似,那么就利用proto一直指向Object的原型对象上!Object.prototype.__proto__ = null;表示到达最顶端。如此形成了原型链继承。
1、Object是作为众多new出来的实例的基类 function Object(){ [ native code ] }
2、原型对象的proto都指向Object.prototype。
3、Object.prototype._proto_指向null ,也就是说Object的原型对象是原型链的尽头。
console.log(Object.prototype._proto_ === null); //true
4、所有函数都是Function的实例(包括Function)
console.log(Function._proto_ === Function.prototype); //true
5、函数的显示原型prototype指向的默认是空的Object对象(但Object不满足)
var fn = new Function(){};
console.log(fn.prototype instanceof Object); //true;
console.log(Object.prototype instanceof Object); //false;
console.log(Function.prototype instanceof Object); //true;
原型链上属性问题
1、读取对象的属性值:会自动到原型链上查找;
2、设置对象的属性值时:不会查找原型链,若当前对象没有这个属性,则直接添加这个属性并设置其值。
3、方法一般定义在原型中,属性一般通过构造函数定义在对象本身。
function Fn(name, age) {
this.name = name;
this.age = age;
}
fn.prototype.sex = "女"; //属性一般不定义在原型对象上, 因为每个实例的属性值不一样
fn.prototype.getName = function(){};
var fn1 = new Fn("fn1", 18);
console.log(fn1.sex); //女 ,原因是fn1对象上没有, 查找原型链中的属性返回
var fn2 = new Fn("fn2", 18);
fn2.sex = "男";
console.log(fn1.sex); //女 还是读取的原型链上的属性
console.log(fn2.sex); //男, fn2发现没有sex属性,就创建了一个sex属性, 并没有改变原型对象上的sex属性
instanceof如何进行判断的?
A instanceof B
A:实例对象
B: 构造函数
原理:
看右边的变量.prototype是否在左边变量的原型链上即可。
1、 如果B函数的显式原型对象(prototype)在A对象的原型链上,返回true, 否则返回false
2、Function是通过new自己产生的实例。
实现:
function instanceOf(left, right){
let proto = left._proto_;
while(proto ){
if(proto===right.prototype){
return true;
}
proto = proto._proto_;
}
return false;
}
例:
function Foo(){
}
var f1 = new Foo();
console.log(f1 instanceof Foo); //true
console.log(f1 instanof Object); //true
console.log(Object instanceof Function);//true;
console.log(Object instanceof Object); //true
console.log(Function instanceof Function); //true
console.log(Function instanceof Object); // true
console.log(Object instanceof Foo); //false
参考文章: