每个函数都有一个prototype属性,它默认指向一个Object 空对象(即原型对象)
原型对象中有个constructor,它指向了函数对象,原型对象添加属性(一般都是方法)
作用:函数的所有实例对象自动拥有原型对象的属性(方法)
function Fun(){
}
console.log(Fun.prototype); // 默认指向一个Object空对象(因为我们没有属性值)
console.log(Fun.prototype.constructor===Fun); // 判断原型对象是否属于Fun构造函数的
//给原型对象添加属性(一般是方法),添加后实例对象就可以访问了
Fun.prototype.test_Fun = function(){
console.log("hello world);
}
var fn = new Fun(); //实例化对象
fn.test_Fun(); // 调用原型对象
显式原型与隐式原型
每个函数 function 都有一个prototype,即显式原型属性
它默认指向了一个空的Object对象 , 因为在创建这个函数对象的时候,该函数内部自动创建了 this.prototype = { },所以这个函数对象的原型属性就是一个空的Object对象
function Fn(){
// 函数内部自动创建语句: this.prototype = {}
}
// 每个函数 function 都有一个prototype,即显式原型属性,它默认指向了一个空的Object对象
console.log(Fn.prototype);
每一个实例对象都有一个__proto__, 可称为隐式原型
当一个函数被实例化的时候,浏览器自动创建了 :this . prototype = new 函数 . prototype,算是继承了父原型的对象属性 所以:实例对象的隐式原型的值,对应着构造函数的显示=式原型的值
function Fn(){
// 内部自动创建语句: this.prototype = {}
}
// 每个函数 function 都有一个prototype,即显式原型属性,它默认指向了一个空的Object对象
console.log(Fn.prototype);
// 每一个实例对象都有一个__proto__, 可称为隐式原型
var fn = new Fn(); // 在创建这个实例化对象的时候,浏览器自动创建了: this.__proto__ = Fn.prototype
console.log(fn.__proto__);
//实例对象的隐式原型的值,对应着构造函数的显示=式原型的值
console.log(Fn.prototype === fn.__proto__); // 返回 true
原型对象图解
总结:
函数的prototype属性:在定义函数时自动添加,默认值是一个空的 Object
对象的__proto__属性:在创建对象时自动添加的。默认值为构造函数的 prototype 属性值
程序员能直接操作显式原型,但不能直接操作隐式原型(在ES6之前)
function Fun(name, age){ // 父原型
// 自动创建 this.prototype = {} 显示原型
}
Fun.prototype.new_fn = function(name, age){ //底层原型对象公共属性
this.name = name;
this.age = age;
console.log(this.name, this.age);
}
var fn = new Fun(); // 创建实例对象,创建时自动生成 this.__proto__ = this.prototype
var ab = new Fun();
var cc = new Fun();
fn.new_fn("zhangsan", 40); // 构造函数直接调用底层原型对象的方法属性
ab.new_fn("tom", 50);
cc.new_fn("hava", 40);
// 正常输出
原型链
访问一个对象的属性时,会先在自身的属性中查找,找到就返回。 如果没有,再沿着__proto__这条隐式原型链向上查找,找到再返回 。
如果始终没找到,则返回 undefined; 隐式原型链,作用:查找对象的属性(就是方法)
function Fn(){
this.test_one = function(){
console.log("hello world");
}
}
console.log(Fn.prototype);
Fn.prototype.test_two = function(){ // 原型对象的方法
console.log("my is a test_two");
}
var fun = new Fn();
fun.test_one();
fun.test_two();
console.log(fun.toString());
以上代码原型链图解
实例化对象 fun 先从自身的堆内存查找,是否有 test_one 方法,有则执行;
实例化对象 fun 从自身查找,是否有test_two 这个方法,发现没有这个方法,那么查找隐式原型属性__proto__这个原型对象,
查找是否有 test_two 的方法,有则执行,没有则返回 undefiend(原型链的尽头了)。