zoukankan      html  css  js  c++  java
  • 关于Javascript夜里再来分析下

    今天周末,夜里没事再把JS梳理一下。有兴趣的可以静下来当成个故事慢慢看。

    首先说的对象。比如 var o={}
    创建一个对象o,但是我们没有看到构造函数。根据面向对象的思路,此处应该有个构造函数。比如C++的new 类型。

    我们应该猜到,这是语法省略了。可经过这么省略,很多事情就变的迷惑了。事实上,完整的写法是:var o = new Object()

    其中,Object()就是一个内置的构造函数。这一步非常关键,是下面一些理论的基础

    在书上,我们常常看到原型(prototype)的说法,原型是函数才能拥有的,即原型是函数的原型。就像上面的Object(),它是一个函数,因此
    它具有原型。但又因为它是内置的函数,因此赋予了很多方法。查看:Object.prototype。

    Object.prototype

    对象o因为通过Object()构造而来,因此它能引用Object的原型(prototype),在浏览器中可以通过o.__proto__来查看

    因此,可以总结出下面一段话:

    原型prototype是函数才具有的,表现形式为:函数.prototype
    由此函数创建的对象可以引用原型,表现形式为:对象.__proto__,换句话说,对象要引用构造的原型,需要给它一个属性来引用,这个引用是__proto__

    现在,我们再来看下函数,相对来说,它是JS中比较复杂的一种类型。但是在这里,我们首先也把它看成对象。原因是:在JS中一切皆对象。
    比如:我们创建一个函数

    function f(){}

    如果在全局中创建,那么它就是浏览器全局对象window的一个属性。 window.f=function(){}

    因为我们说函数f是一个对象,那么就问,它的构造函数是谁呢?这个问题如果不搜索一些资料还是很难理解

    函数作为对象,必定也有一个构造函数,它的构造函数就是Object(),也就是,函数都是Object()的一个实例。但是它又会把自己的构造函数设置成自己
    这个问题可以通过浏览器查看验证。我们总结一句话:函数都是Object的实例,它的构造函数是自身。

    因此,我们会看到f.__proto__指向的就是Object的prototype..

    又因为,f.__proto__指向Object,因此通过此函数构造出来的对象就能引用Object的prototype,其实就是上面所说的原型链。我相信这些推导难不住聪明的程序员

    下面通过一段对话对上面进行总结:

    问:
    function f(){}
    var o = new f()
    为什么o能引用Object的prototype?

    => 函数f也是对象,它的构造函数是Object(),因此f.__proto__指向Object.prototype
    f.prototype={
      construtor:f,
      __proto__:Object.prototype 
    }

    又因为对象o通过f构造而来,而此 o.__proto__=f.prototype,根据原型链往上引用查找,就可以引用到Object的prototype。

    --------

    下面,我们继续讨论函数

    函数是可被任意调用的一段代码,内部可以使用this。任意调用是什么意思呢?就是说它没有自主权。就像一间房子,谁能出房租就租给谁占用。

    funciton f(){
        return this.name;
    }

    看下这段代码,字面上看就是打印this.name。在面向对象中,this表示当前对象。
    可以认为这是一段静止的代码(自由、无自主权、需要依赖某个对象),谁调用它,它就打印谁的name

    为了方便,它有一个call和apply的方法,形式为:函数.call(对象,参数)。这样一看更容易明白,函数是自由的。比如:
    var o = {}
    o.name = "tianya"
    f.call(o,null) //输出"tianya"

    但是先等等,这个call从哪来的?

    如果前面的原型链理解的话,我们知道,一个对象的方法,要么是它自已定义的,要么是从祖先"继承"过来的。那么函数f的这个call从哪来的呢?
    前面说过,f的构造函数是指向自己,即 f.constructor=this,这个构造函数的__proto__指向的是原生f(斜体)的prototype。那么我们继续往下
    问这个原生f又是怎么回事儿?

    从哲学上来说,我们可以无限的往下追问,但是往往都会有一个尽头。就像windowsAPI,无论我们把它的使用了解的多么清楚,但是只能停留到API的

    那一层,就是追问的尽头,底层实现再也没法查看。因此,我们可以说,这个斜体的原生f就是语言内置的。

    因此从这可以说,一个函数(同时也是一个对象,这样说是有点挺绕的),可以从两个方向来继承,1. 从构造函数的方向继承祖先的一些方法 2. 直接
    继承Object()。而call,apply等,正是从构造函数那个方向继承过来的。(注:这一段可以通过浏览器查看)

    再回到正文,call和apply的出现,可以达成一些效果。就是一个方法明明是其它对象的,但也可以借来调用。到这里,我们可以看出,函数是自由的,
    仿佛它不是本质归属于哪个对象。

         

  • 相关阅读:
    学习工具
    Qt 之 QApplication
    Qt中常用的类
    关于在Qt里让程序休眠一段时间的方法总结
    Qt setWindow setViewPort
    ajax回调数据 Structs has detected an unhandled exception 问题
    Struts2配置拦截器自定义栈时抛异常:Unable to load configuration.
    es6之map解构数组去重
    ES6之对象的方法
    ES6之genorator和yield使用(迭代器)
  • 原文地址:https://www.cnblogs.com/tinaluo/p/13702314.html
Copyright © 2011-2022 走看看