`
oojdon
  • 浏览: 39654 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

我悟JavaScript

阅读更多

信息的本质

计算机,至少我的这个计算机,只认识0和1,计算机的处理对象是信息,信息被0,1量化或者数字化,0,1本身没有意义,它需要和它存在的场景或者上下文来共同表示信息,在不同的上下文,同样的01序列可能表示不同的信息,比如整数,浮点数,字符串甚至机器指令,所以机器指令,整数,浮点,字符,字符串它们本质就是数据。


冯氏模型编程的核心:数据,代码

数据是我们用01量化的宇宙万物,不抽象就是01,抽象了就是抽象数据类型,结构。

代码是逻辑的表达,数据在逻辑流中被操纵,代码是任务的步骤,它也是算法。

原始的编程本质是指令和数据,高级的编程应是结构+算法+抽象+架构。数据结构和算法是属于计算机科学,它独立于应用和程序设计语言,它是数学上成立的东西,应用和语言都是不断的抽象它们以快速的解决应用的问题。

 

古代我们把它代码和数据分开,比如C语言,因为冯若依曼机的设计就是一个内存修改器,指令修改数据,映射到编程语言那就是代码和数据,到了某个年代,人们发现,如C语言这样的编程不够高效,复用度也不高,于是又抽象了一把,把数据和代码和为一体,命名为对象,对象有一个重要的特点就是隐藏了数据,向外提供接口服务,这个比较贴近问题领域空间,所以这种编程抽象一直沿用到了至今,这种基于对象的编程方式在系统实现级别也表现得相当优秀,我们把稳定的算法和数据结构实现封装起来,作为遗产。


何为对象

对象是一个离散的自主个体,映射到计算机中是代码和数据和组合体,对象之间如果有共性,在类定义级别就会用到继承机制,对象提供服务,如果同样的服务有多个对象可以完成,这里就用到多态,对象应该有自己的本真状态和行为,但是它还应有一个特性,那就是在不同的场景下表现出不同行为和特征(DCI编程范式),明确这些概念,我们开始进入JavaScript的世界。


JavaScript的数据,代码和对象

JavaScript中的数据:字符串string,数字number,布尔boolean,nullundefined

JavaScript中的代码:函数function

JavaScript中的对象: 对象就是数据和代码的结合体,数据就是上面的5种,代码就是函数,创造对象在JavaScript中相当的简单,比如表达我这个对象的代码是 var oojdon = { } ,现在我是1987228号的我,那天我刚刚出生,一片空白,到了现在会写java程序,oojdon.canWriteJava = function() {}JavaScript中的对象就是一个哈希表,或者关联数组,或者key value对。



理解JS的代码

js中的代码用function来表示,但是function本身也是对象,一旦将代码当做对象,系统就统一成一切都是数据,代码也是数据,它只不过可以被执行,数据是抽象的概念,它可以表示被代码操纵的数据,也可直接表示代码。代码对象在运行时不能单独存在,它有个实例化的概念,这个时候它必须拥有数据。对象和闭包是组织代码和数据两种形式。

 

 

深入函数

函数是表达代码的地方,也就是表达程序逻辑的地方,在JS中函数可以被玩出各种花样

 

1,定义函数

 

function hello() {
      return "hello oojdon";
}

 

 2,函数是数据

 

var hello = function() {
     return "hello oojdon";
}

hello();

 

 3,匿名函数

 

document.onmousemove = function (evt) { alert(evt.pageX); };

 

4,自调用

 

(function() {
    var h = "hello oojdon";
})();

 

5,嵌套函数,并返回函数

 

function  makefunc(x)  {
     return   function ()  {  return  x; } 
} 
 

JS中的函数可以用任意数目的参数来调用,而不管函数定义中的参数名字是多少个,由于函数是宽松类型的,就没有办法来声明所期望的参数类型,并且向任何函数传递任意类型的参数都是合法的,如果这样做,我们怎么样才可以全部得到这些参数呢?例如,a函数只有一个参数,但是调用时却传了3个参数,怎们获取后面两个?玄机在函数内部的一个标识符arguments,这个标识符引用一个叫Arguments的对象,这个对象看似数组实不是数组,arguments.length表示实际穿了多少个参数,通过位置坐标来访问各个参数,比如arguments[0],arguments[1],这个对象还有一个属性callee用来引用当前正在执行的函数。

 

函数也是对象,JS的设计让每个函数对象都具备了一些属性和方法,如下

 

1,只读属性length,指函数的参数个数

2,属性prototype,引用预定义的原型对象,当函数作为构造函数时非常有用,具体请看下面的分析

3,方法apply和call,作用相同的方法,就是被别人调用,不同点就是参数的传递方式,比如被oojdon调用,参数是java和js,那么代码如下

 

f.call(oojdon,"java","js");
f.apply(oojdon,["java","js"]);
 


JavaScript中的原型prototype

刚才有提到对象的共性,我们把思维抛向外太空,地球是多么的渺小啊,人类又是多么多么的渺小啊,眼前存在的这些对象有什么共性吗?共性包括用数据表示的特征和用代码来表示的行为服务,如果找到了这些共性,我们可以把它塞进一个人为创造的对象中,然后真实的对象通过某种机制来关联它,这样是不是很自然? JS的设计者就是这样做的,它引入了prototype, prototype是一个对象,在JS中每一个对象都会关联一个prototype对象,由于prototype对象也是一个对象,所以就形成了一条链,链的根部就是JS设计者在太空中想出来的共性对象,显然这个对象就没有自己的prototype了,这个对象按照JS设计者的理念有如下属性和行为:

 

1,constructor属性,它引用了初始化这个对象的构造函数

2,toString方法,描述对象

3,toLocaleString方法,让对象在世界各地描述自己

4,valueOf方法,在JavaScript中,可以说一切皆数据,在个方法会在对象被当做数据时自动调用

5,hasOwnProperty方法,判断是不是继承来的属性。

6,propertyIsEnumerable方法,判断属性是否可用for/in循环枚举

7,isPrototypeOf方法,判断该方法所属的对象是否是参数的原型对象


看图




 Class的来历

上面我们有提到JavaScript创建对象的方式,相当的优雅,var o = {} ,可是有个问题,如果两个对象有相同的属性和代码,我们岂不是要写两次,如果3个对象我们得写3次,如果n个呢? 这是不可接受的,于是人们发明了一种方法,把这些共同的属性和代码写到一个叫Class的东西中,然后要对象的时候用 new Class 这种形式来获得,怎么样不错吧? 不过又有问题,在像Java这种语言,Class new出来的对象都有自己的属性,但是是公用代码的,在JS中则不是这样,我们说了,JS的对象里全是数据,每个对象都有自己的一份,这个对代码来说就浪费,因为这是可以完全可以共享的,于是上面的prototype又派上用场了。



对象创建的本质

通过上面的分析,对象创建用new Class的形式是一定的,在Java等语言中,讨论到此为止,但是在JS中,却还得继续研究,那就是太空中那个共性对象怎么和new出来的对象关联的问题,在Java中,是虚拟机自动把一个Object类上的方法和属性送到了new出来的对象上,在JS中是通过new Object这个内置函数来实现的,我们创建一个对象,比如先有一个能够被new的函数,Object是内置的函数对象,这个对象的prototype对象关联了那个太空共性对象,刚才var o = {}其本质就是new Object,这个new的过程就是Object函数执行,然后把Object那个prototype 介绍给 o,现在oprototype对象指向了Object prototype对象.

因为我们要写Class,所以必须写自己的函数来new 对象,当你写完这个函数,JS引擎给你生成这函数对象,这个对象的prototype就指向了Objectprototype,那么用这个函数new出来的对象就形成一个链,除了函数对象外每个对象自己的prototype对象对外界是不可见的。对象可以掩盖原型对象的那些属性和方法,一个构造函数原型对象也可以掩盖上层构造函数原型对象既有的属性和方法。这种掩盖其实只是在对象自己身上创建了新的属性和方法,只不过这些属性和方法与原型对象的那些同名而已,JavaScript就是用这简单的掩盖机制实现了对象的多态性,与静态对象语言的虚函数和重载(override)概念不谋而合。



JavaScirpt中的this

This是自我的意思,在Java这种语言中,一个对象中的this就是指当前这个对象,但是在js中的this则比较特殊,在java中,一个代码是写在一个类中,写完即固定,可是在js中,代码是一种数据,数据是可以传来传去的,所以在js代码中的this必须要搞清楚谁在用这个代码,因为this指的就是用这个代码的那个东东,一个函数中的this指调用者个函数的对象,如果不指明调用者,则thisJS引擎的宿主对象,在浏览器中就是window,上代码

 

function docReady() {  
     alert(this)//这个this指的就是window对象  
}  

window.onLoad = docReady;  
 



JavaScript的执行

JS是动态语言,它是像Java那样要编译一次的,可是js还是有自己的预编译阶段,也就是预先扫描<script></script>这里面的内容,然后分析,然后做一些手脚,然后开始解释执行,那么做了什么手脚呢?它把所有的变量和函数都解析为宿主对象的属性,就以浏览器为例吧,就是window的属性,所有在函数外面定义的变量都具备全局作用域,所有未定义就直接赋值的变量也是全局作用域,所有window对象的属性都是全局作用域,函数里面定义的变量具有函数作用域,函数的函数里面的变量就再嵌套作用域,依次类推,看示例代码

 

// 全局
var likesToPlay = "Poker";
function getGame () { 
      // 局部
     var likesToPlay = "Hold ‘em"; 
     // 全局
     playOnline = true; 

     return likesToPlay; 
    // 返回"Hold ‘em" 
}
 

JS没有块级作用域,不像java等语言,所以你在代码最后定义的变量在代码前面也是可以访问的,即便是循环语句中的变量都是具备函数作用域或者全局作用域,并不会有临时变量存在,这些作用域关系在函数定义的时候全部确定,而不是在调用时确定,书面一点的说法就是,JS中的函数是通过词法来划分作用域的,而不是动态的划分作用域,每当代码运行进入一个函数时,Javascript引擎就会自动创建一个新的作用域,然后把这个新作用域作为当前作用域的子作用域,然后把当前的代码作用域切换到这个新作用域。当代码退出函数时,这个作用域销毁,把代码作用域交还给他的父作用域,这就是作用域链,执行函数的时候js引擎会生成一个调用对象来做这个函数的全局对象,所以函数内的变量都是这个调用对象的属性,如果函数嵌套,也以此类推,如果函数查找某个变量的时候首先会在自己的调用对象中找,依次类推,最后找到顶层对象window,当一个函数返回一个函数并被保存的时候,这样就形成了闭包,因为每次执行都是不同的调用对象,所以就会形成代码和执行环境的综合体。


看图


 

 

再上一张大图


  • 大小: 95.5 KB
2
2
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics