一、原型
1.每个函数都有prototype属性,即显式原型属性,它默认指向一个空对象(原型对象)。
function Fn() { }
console.log(Fn.prototype) //{}
2.每个实例对象都有一个__proto__,即隐式原型属性,它的值为其对应构造函数的显式原型的值
function Fn() { }
var fn = new Fn();
console.log(fn.__proto__) //{}
console.log(fn.__proto__===Fn.prototype) //true
3.原型对象作用:把常量和方法独立到自身里,供给其它实例对象使用
function Fn() { }
Fn.prototype.name = '我是原型对象上的属性'
Fn.prototype.say = function () {
console.log("我可以被其它实例对象使用")
}
var fn = new Fn();
console.log(fn.name) //我是原型对象上的属性
fn.say() //我可以被其它实例对象使用
总结:
1.函数的prototype属性,在定义函数时自动添加,默认值为一个空Object对象。
2.实例对象的__proto__属性,创建对象时自动添加的,默认值为构造函数的prototype属性值。
二、constructor
1.每个函数都有prototype属性,而prototype属性中又有constructor属性,它指向函数本身。
function Fn() { }
console.log(Fn.prototype.constructor===Fn) //true
console.log(Fn.prototype)
2.函数也是Function的实例对象,所以也有__proto__属性,它也有constructor属性(本身并没有,继承自它的原型对象(Function.prototype)),指向了构造它的构造函数。
function Fn() { }
console.log(Fn.__proto__.constructor===Function) //true
console.log(Fn.__proto__)
总结:
1.每个函数的的显式原型的构造器都指向它自己,而每个实例对象的隐式原型的构造器指向了构造它的构造函数。
三、原型链
1.访问一个对象的属性时,先在自身属性中查找,找到返回,若没有,再沿着__proto__这条链向上查找,找到返回,如果最终没找到,返回undefined。
2.作用:查找对象的属性、方法。
3.原型链尽头是Object.prototype,它的__proto__为null。
function Fn() { }
Fn.prototype.sayHello = function () {
console.log("Hello! Fn");
}
var fn = new Fn();
fn.sayHello = function () {
console.log("Hello! fn");
}
fn.sayHello(); //Hello! fn 若没有fn.sayHello则输出Hello! Fn
图解:
总结:
1.读取对象的属性时,会自动到原型链中查找。
2.方法一般定义在原型中,属性一般通过构造函数定义在对象本身上。(详情见我的另一篇博客—javascript创建对象及继承方式)
有可能遇到的原型相关面试题
function f() { };
const a = f.prototype;
const b = Object.getPrototypeOf(f); //Object.getPrototypeOf方法返回指定对象的原型
console.log(a === b);
解析:
分析第3行:获取f的原型对象赋值给b,所以有f.__proto__ === b,f.__proto__ === Function.prototype , b === Function.prototype
分析第2行:a === f.prototype ,所以二者不相等
答案:false
const a = {};
const b = Object.prototype;
console.log(Object.getPrototypeOf(a) === b);
a.__proto__ === Object.prototype
答案:true
js获取原型方法?
1.p.__proto__
2.p.constructor.prototype //p.constructor指向其构造函数,也就是构造函数.prototype
3.Object.getPrototypeOf(p)
//p为实例对象
更多练习题见我的令一篇博客—原型和原型链相关题型