JS难点剖析-原型&原型链

 js的原型&原型链&闭包,在很多人看来是区分JS程序员水平的关键知识点,当然对这句话我不是十分赞同。但是掌握这几个核心知识点总是没错滴!

    直接上代码:

<script type="text/javascript">

//全部为函数对象类型(function)
function f1(){}
var f2 = function(){}
var f3 = new Function() 

//全部都是普通对象类型(object)
var o1 = {}
var o2 = new Object()
var o3 = new f1()

console.info(
  typeof f1,
  typeof f2,
  typeof f3,
  typeof o1,
  typeof o2,
  typeof o3
)

//function function function object object object

var obj = new f1();
f1.prototype.name = 'banyoukang';
console.info(obj.__proto__.name)//banyoukang
console.info(f1.prototype)// f1 { name="banyoukang"}
console.info(obj.__proto__)//f1 { name="banyoukang"}

</script>

你可以自己试试这段代码,并想一下其输出结果,为什么?下面让我们掰扯掰扯这段代码:

  1. 关于JavaScript对象
    在JavaScript中,一切都是对象,但是和Java不同的是:这些对象是分类型的。主要分为function(函数对象)和object(普通对象)。

    //全部为函数对象类型(function)
    function f1(){}
    var f2 = function(){}
    var f3 = new Function()
    
    //全部都是普通对象类型(object)
    var o1 = {}
    var o2 = new Object()
    var o3 = new f1()
    
         

    <1>在这里,f1应该是我们开发中最常用法,f2用的应该也挺多,只是多了一个引用罢了。但是,f3这种写法倒是不多见的,其实f1,f2在创建的时候,JS会自动通过new Function()的方式来构建这些对象,所以都是f1,f2,f3本质上并没有什么区别。注:

    var f3 = new Function('var temp = 100; this.temp = 200; return temp + this.temp;');

     

    alert(f3())

    //弹出300,()将会执行引号中的内容,类似于eval函数)

    <2>关于o1和o2我们都可以理解(对象字面量、使用new表达式来创建对象),但是o3虽然是f1函数new出来的,但是和f1缺不是一个类型的,看打印结果可以发现,一个是函数对象一个是普通对象。

  2. 关于原型和原型链

          在JavaScript中,每一个对象都有一些属性,包括prototype和__proto__,其中prototype就是原型对象(prototype其实就是函数的一个属性),其作用就是保存对象的一些属性和方法(你可以通过f1.prototype.show = function(){} 给f1的prototype赋值一个方法),但是prototype对于对象本身是隐藏起来的,因为它是原型对象prototype的属性而不是对象本身的属性(你可以通过f1.prototype.show()来调用,但是不能通过f1.show()来调用)。关于__proto__,这才是原型链真正起作用的地方,它在普通对象和函数对象中都存在, 它的作用就是保存父类的prototype对象,JS在通过new 表达式创建一个对象的时候,通常会把父类的prototype赋值给新对象的__proto__属性,这样,就形成了一代代传承...  

function f2(){}
f2.prototype.name='banyoukang';
var test = new f2();

console.info(test.name)//banyoukang

    注:可以通过test.__proto__来查看原型链

        

        _proto_保存着父类的prototype的属性,当查找一个属性的时候,先看看自己有没有这个属性,如果没有就顺着原型链往上依次查找(注:不会查找自身的prototype属性)。

3.总结

        <1>prototype就是对象的一个属性,这个属性也是一个对象(类似Java类中把其他类的对象定义成一个成员变量),专门用于储存准备传递到子类的方法和属性。

        <2>__proto__就是prototype中属性和方法的实际传递者,当你new一个对象的时候,会把父类的prototype赋值给新对象的__proto__属性,这样你在子类的__proto__属性中就可以拿到父类传给你的属性和方法。

        <3>不同的对象的原型链是截然不同的,比如父类和子类:

            function f1(){}

            var test = new f1()

        f1的原型链:f1->Function.prototype->Object.prototype->null

        test的原型链:test->f1.prototype->Object.prototype->null

        从上面的实例我们可以看到:对象的prototype属性是为子类服务的,是子类创建的核心,决定了子类的数据类型

        这篇博文是自己试验加上阅读其他大神的博客总结出来的,如果您阅读的过程中发现其中存在问题或者有指教的地方,欢迎拍砖,共同进步!

猜你喜欢

转载自my.oschina.net/u/3460260/blog/1928074