javascript-原型链

先来看一段代码:

<!DOCTYPE html>
<html>
<script type="text/javascript">
function show(){
    console.log(typeof(x)); //undefined
    console.log(typeof(10));//number
    console.log(typeof("asdf"));//string
    console.log(typeof(true));//boolean
    
    console.log(typeof(["1","2"]));//object
    console.log(typeof(new Object()));//object
    console.log(typeof(null));//object
    console.log(typeof(new Number(10)));//object
    console.log(typeof(new Boolean(true)));//object
    console.log(typeof(new String("asdf")));//object
    
    console.log(typeof(function(){}));//function
    console.log(typeof(new Function("x","y","return x + y;"))); //function
    var fn=new Function("x","y","return x + y;");
    console.log(typeof(fn));//function
    console.log(fn instanceof Function);//true
    console.log(fn instanceof Object);//true, 由此可以看出 Function 本身是一个类。
}
show();
    
</script>
</html>

上述代码可以看出,javascript中对象分为两种 Object对象 和 Function对象,而Function对象本身又是Object对象的一个子集。

Object对象很容易理解,那么什么事Function对象,可以认为只要我们声明了一个function,如:function fn(){},或者使用new 创建一个function 如:var fn=new Function("x","y","return x + y;"),这时就可以认为是创建了一个 Function 对象.

那么什么是普通Object对象?只要我们使用new Object() 创建的对象都认为是普通对象,其他创建对象的写法,如:var dd={} 其实底层都是使用new Object(),这在编译原理中被称为 语法糖。

 这些和原型又有什么关系? javascript 中 每个Function对象都有一个属性是原型对象prototype ,普通对象没有prototype属性但是都有一个__proto__属性。

再来看一段代码:

    function Animal() {};// 声明了一个function就相当于创建了一个Function对象
    console.log(typeof (Animal)); //function
    console.log(typeof (Animal.prototype)); //object , 每个Function对象都自动获得一个原型属性
    console.log(Animal.prototype);// Animal {}, 每个Function对象都自动获得一个原型属性
    console.log(Animal.constructor);// Function(),Animal 是Function的一个实例,该实例的constructor属性指向 创建他的构造函数(这里是Function())。
    console.log(Animal.prototype.constructor);//Animal(),Function对象的原型属性有一个constructor属性,指向Function对象自己
   console.log(Animal.__proto__);// function()    
   console.log(Animal.__proto__.constructor);// Function(),Animal 是Function的一个实例,每个Function实例都有一个 __proto__ 指向 Function.prototype console.log(Animal.prototype instanceof Object); //true, prototype 是Object的一个实例 console.log(Animal instanceof Function); //true,Animal 是Function的一个实例 var ani=new Animal(); // 创建一个Animal的实例 console.log(typeof (ani)); //object console.log(ani.prototype); //undefined,普通对象没有prototype属性 console.log(ani.constructor);// Animal(),实例的constructor属性指向 创建他的构造函数 console.log(ani.__proto__); //Animal {},实例的__proto__ 指向创建他的Function的prototype,这里是 Animal.prototype console.log(ani.__proto__===Animal.prototype)//true,实例的__proto__ 指向创建他的Function的prototype,这里是 Animal.prototype

 看完上述代码,也许对 Animal() {} 和 new Animal()清楚了,但是对Function和Object更加迷惑了,再来看一段代码:

 

    console.log(typeof (Function)); //function, Function本身也是一个function和 Animal() {} 一样
    console.log(typeof (Function.prototype)); //function
    console.log(Function.prototype);// function() , 这是Function比较独特的地方,他的prototype 是 function()
    console.log(Function.constructor);// Function(),Function是Function自己的一个实例,该实例的constructor属性指向 创建他的构造函数(这里是Function())。
    console.log(Function.prototype.constructor);//Function(),Function对象的原型属性有一个constructor属性,指向Function对象自己
    console.log(Function.__proto__.constructor);// Function(),Function是Function自己的一个实例,每个Function实例都有一个 __proto__ 指向 Function.prototype
    console.log(Function.prototype instanceof Object); //true,Function本身是Object的一个子集,因此这里输出true
    console.log(Function instanceof Function); //true,Function是Function自己的一个实例
    
    
    console.log(typeof (Object)); //function , Object本身也是一个function和 Animal() {} 一样是一个Function实例
    console.log(typeof (Object.prototype)); //object
    console.log(Object.prototype);//  Object {}, 每个Function实例都自动获得一个原型属性
    console.log(Object.constructor);//  Function(),Object()是Function的一个实例,该实例的constructor属性指向 创建他的构造函数(这里是Function())。
    console.log(Object.prototype.constructor);//Object(),Function实例的原型属性有一个constructor属性,指向Function对象自己(这里是Object())
    console.log(Object.__proto__.constructor);// Function(),Object()是Function的一个实例,每个Function实例都有一个 __proto__ 指向 Function.prototype
    console.log(Object.prototype instanceof Object); //false,这里是Object比较特殊的地方,不知道为何不是true
    console.log(Object instanceof Function); //true,Object本身也是一个Function实例

 

总之,Function和Object是两个比较特殊的实例,我们通过一个图(原型链图)来说明自定义的Animal()和 javascript预定义的Object()及Function()的关系:

 javascript 中所有的类都继承自Object(),那么这种继承方法(原型继承)是如何体现出来的呢?我们再来看一段代码

 

//定义一个Animal() 
function Animal(){this.color=""; this.movestyle="run......"};
// 通过原型的方式给Animal添加一个show方法
Animal.prototype.show=function(){console.log("Color:"+this.color+";movestyle:"+this.movestyle);}
// 定义一个Dog()
function Dog(){this.color="golden"};
//将Dog()的原型设定为一个Animal实例,这样Dog就继承了Animal的所有内容
Dog.prototype=new Animal();
//对象实例的constructor属性,指向创建该实例的构造函数,经过上一步,constructor的值也被设定为Animal()了,所以需要重新设定为Dog()
//如果没有这一步Dog的对象会报告浏览器说它们是Animal()创建的。。
Dog.prototype.constructor=Dog;
// 创建一个Dog()实例
var dog=new Dog();
// 该实例继承了show方法和movestyle属性,并覆盖了Color属性
dog.show();
console.log(dog.constructor);//Dog()
//Animal { show=function()},Dog.prototype是一个Animal实例 所以该实例的__proto__就是Animal.prototype
console.log(Dog.prototype.__proto__);
console.log(Dog.prototype.__proto__===Animal.prototype);

//Dog { movestyle="run......",  color="",  constructor=Dog(),  more...}
//比较神奇的是这里,Dog.prototype是一个Animal实例 ,但是我们又把Dog.prototype.constructor设定为Dog。
// 所以dog具有Animal()的属性和方法,但是constructor=Dog()。
console.log(dog.__proto__);
console.log(dog.__proto__===Dog.prototype);//true
console.log(dog.__proto__.__proto__ === Animal.prototype);//true

console.log(dog instanceof Dog);//true
console.log(dog instanceof Animal);//true

 我们把Animal()和Dog()的关系用图的方式表示出来,如下图:

说了那么多,那么到底什么是原型链,访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着__proto__这条链向上找,这就是原型链。

在原型链中,最核心不是"prototype" 而是"__proto__"。通过"__proto__"一级一级向上查找,

最终都会到Object.prototype.所以说javascript中Object是所有“类”的“基类”。

原型继承和传统的继承方相比是一种完全不一样的思路,切忌死搬硬套, 原型继承中的继承 正是通过原型链来体现的。

posted on 2016-12-09 10:09  气质请注意  阅读(387)  评论(0编辑  收藏  举报

导航