JS高级(2)函数高级 — 原型与原型链

🌟 原型与原型链

1. 原型prototype

每个函数都有一个prototype属性,它默认指向一个Object空对象 (即原型对象),里面没有我们的属性;原型中有一个属性constructor,它指向函数对象;构造函数和原型对象相互引用

function Fn(){
    console.log("hello");
};
console.log(Fn.prototype); //Object

//验证constructor
console.log(Fn.prototype.constructor === fn); //true

//给原型对象添加属性(一般是方法)---> 实例对象可以访问
Fn.prototype.test = function(){
    console.log("test()");
};

//创建实例来测试方法是否添加成功
var fun = new Fun();
fun.test();

2. 显示原型与隐藏原型

每个函数都有一个prototype,可称为显式原型(属性) ,默认指向一个空的Object对象;每个实例对象都有一个__proto__,可称为隐式原型(属性),也默认指向一个空的Object对象

对象的隐式原型的值为其对应构造函数的显式原型的值,在创建实例对象的同时把prototype的值复制给了__prototype__,内部语句:this.__proto__ = Fn.prototype; 

function Fn(){ //内部语句:this.prototype = { }; 添加prototype属性
    
};
var fn = new Fn(); //内部语句:this.__proto = Fn.prototype;
console.log(Fn.prototype === fun.__proto__); //true

//给原型添加test方法
Fn.prototype.test=function(){
    console.log("test");
};
fn.test();
//fn先寻找自己本身的__proto__里面是否含有test方法,如果没有,则去和prototype共同指向的空对象Object中找

3. 原型链

访问一个对象的属性时,先在自身属性中查找,找到返回;如果没有,再沿着__proto__这条链想上查找,直到Object构造函数的原型对象(原型链的尽头),如果仍然没有则返回undefined

Object本身是JS中内置的一个构造函数,函数也是一种特殊的对象,所以Object构造函数本身就含有prototype这个显式原型;Fn构造函数的prototype是指向一个Object空对象的,但这个Object空对象实际上是通过Object构造函数new出来的,所以其__proto__属性必然和Object构造函数对象中的prototype属性指向同一个对象。

1) Object构造函数/原型/实例对象的关系

var o1 = new Object();
var o2 = { };

 2) 构造函数/原型对象/实例对象的关系

 function Foo( ){  };

*其中Function = new Function( );,也就是说Function自己也是Function构造函数的实例对象。

 4. 相关问题

(1)函数的显式原型prototype指向的对象默认是空Object,这个空的Object是Object构造函数的实例对象(但Object的prototype并不是Object的实例对象)

console.log(Fn.prototype instanceof Object);//true
console.log(Object.prototype instanceof Object);//false
console.log(Function.prototype instanceof Object);//true

(2) 所有的函数都是Function的实例对象(包含Function)

console.log(Function.prototype === Function.__proto__); //true

(3) Object的原型对象是原型链的尽头 (Object的原型对象也是Object的实例对象,但是这个实例对象的__proto__没有值)

console.log(Object.prototype.__proto__); //null

5. 属性问题

查找属性时,先从自身找,没有的话会自动到原型链中查找。

function Fn(){
};

Fn.prototype.a = "xxx";
var fn1 = new Fn();
console.log(fn1.a); //xxx
//1. 读取实例对象的属性值时,会自动到原型链中查找

var fn2 = new Fn();
fn2.a = "yyy";
console.log(fn1.a, fn2.a); //xxx yyy
//2.设置实例对象的属性值时,如果当前对象没有此属性,直接添加此属性并设置其值

var fn2 = new Fn();
console.log(fn2.a); //xxx
// 3. 当实例对象中没有该属性时,会自动到原型链中查找,如果本身有就返回自身的

属性存自身,方法存原型。

function Person(name, age){
    this.name = name;
    this.age = age;
};
Person.prototype.setName = function(name){
    this.name = name;
};
var p1 = new Person("jerry",23);
p1.setName("bob");

 6. 探索instanceof

表达式: A(实例对象)instanceof B (构造函数)

如果B函数的prototype对象在A对象的原型链上则返回true,否则返回false

 函数Foo的prototype是一个对象,由Object构造函数创建,所以也是Object的一个实例,而Object构造函数的原型对象就是原型链的终点。

console.log(Object instanceof Function); //true
//Object是Function的实例,也就是Object = new Function();

console.log(Object instanceof Object); //true
//Object作为实例对象的时候,其__proto__值和Function的prototype一致,而Function的prototype也是对象,所以它也是Object产生的实例对象
 
console.log(Function instanceof Function); //true
console.log(Function instanceof Object); //true

function Foo(){};
console.log(Object instanceof Foo); //false

 7. 面试题

//测试题1
function A (){

};
A.prototype.n = 1;
var b = new A();
A.prototype = {
    n:2,
    m:3
};
var c = new A();
console.log(b.n, b.m, c.n, c.m);//1, undefined, 2,3

//测试题2
var F = function(){};
Object.prototype.a = function(){
    console.log("a()");
};
Function.prototype.b = function(){
    console.log("b()");
};
var f = new F();
f.a();
f.b(); //f.a is not a function
F.a();
F.b();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值