Object.prototype 原型和原型链

414 阅读2分钟

原型

Javascript中所有的对象都是Object的实例,并继承Object.prototype的属性和方法,有些属性是隐藏的。换句话说,在对象创建时会存在预定义的属性,其中有一个属性就是原型对象。
在函数对象中存在原型对象prototype,在普通对象中没有prototype,但存在__proto__。或者说使用function定义的对象与使用new操作符生成的对象之间有一个重要的区别,这个区别就是function定义的对象有一个prototype属性,使用new生成的对象就没有这个prototype属性,存在__proto__.

var o =new Object();    
console.log(o.__proto__);
console.log(o.prototype);//undefined

var fn = function(){} 
console.log(fn.prototype);//Object {constructor: function}
var f1 = new fn();
console.log(f1.__proto__);
console.log(f1.__proto__===fn.prototype);//true

原型链

那么__proto__是什么?每个对象都会在其内部初始化一个属性,就是__proto__。 普通对象中的__proto__是什么呢? Object的本质函数对象,是通过new Function()创建,所以Object.__proto__指向Function.prototype。同理,Function也是函数对象,因此Function.__proto__同样指向Function.prototype。 Object.prototype对象也有__proto__属性,但它比较特殊,为null。这个由__proto__串起来的直到Object.prototype.__proto__为null的链就是原型链。

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

当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去__proto__里找这个属性,这个__proto__又会有自己的__proto__,于是就这样 一直找下去,也就是我们平时所说的原型链的概念。

var Fn = function(){};
Fn.prototype.Hello = function(){
		console.log("Hello World");
    }
var f1 = new Fn();
f1.Hello();//Hello World
//上面的代码解析
首先var f1=new fn(),f1是Fn的实例,可以得出f1.__proto__=Fn.prototype。
当我们调用f1.hello()时,首先f1中没有Hello这个属性,于是,它会到他的__proto__中
去找,也就是Fn.prototype,而我们在上面定义了 Fn.prototype.Hello=function(){};
于是,就找到了对应的方法。

下面是一个较为复杂例子的分析


        var Person = function() {};
        Person.prototype.Name = function() {
            console.log("person name");
        }
        Person.prototype.Sex = "male or female";
        
        var Younger = function() {};
        Younger.prototype = new Person();
        Younger.prototype.Age = function() {
            console.log("14-28")
        };
        Younger.prototype.Sex = "female";
        
        var Ann = new Younger();
        Ann.Name(); //person name
        console.log(Ann.Age()); //14-28
        console.log(Ann.Sex); //female
        

对上述代码我们可以做如下分析:

综上可得:Ann.__proto__.__proto__ = Person.prototype
Ann本身没有Name()方法,于是从Ann.__proto__(Younger.prototype)中找,
仍没有找到于是在向上一层Ann.__proto__.__proto__(Person.prototype)中寻找,
最终在Person.prototype中找到对应的方法并调用。

同理,Ann本身并没有Age()方法,但在Ann.__proto__(Younger.prototype)存在。
对于Ann.Sex,在Ann.__proto__(Younger.prototype)中已经能够找到,
便不再向上寻找,因此输出是female。