本系列属于进阶系列,语经常使用语法等不在本系列介绍范围以内。javascript
在我刚开始作一个程序员并开发项目的时候,我老是喜欢使用开发语言的各类特性,每次m$发布新版C#的时候我老是会把开发者预览版下好,亲自体验,并指望从中得到快感,每次使用新的语言进行程序设计的时候,我老是喜欢掌控他有趣的地方,尽管不少与软件工程有悖。这彷佛让我出过不少风头,别人的问题彷佛没有什么能难倒个人,后来在我开始从工程领域思考问题的时候,我发现不少特色给我带来的"编程快感"引起的麻烦超过了快感自己的价值,不少地方难以被同项目的人理解,这些奇淫技巧在我学习jquery源码的时候也给我带来了不小的麻烦(jq源码使用了大量js技巧),没有相比于更工程化的backbone.js的源码易于学习,这一年我学会了在中间作取舍,这是必须的。
不过我认为我快速学习的能力须要保留,我通常把我学过的高级编程语言分为“面向过程”,“面向对象”,“函数式”,“并发式”,这让我学一个新语言的时候会很是之快速,不过大多数语言都是把特色混杂在一块儿了。java
本系列内容为本人平时项目实践和参照MDN,MSDN,《javascript语言精粹》,《Effective Javascript》等资料,而且整理本身EverNote的平常积累整理所写,时间太长有一些代码样例来源不可考。本系列不容许任何形式的转载,谢谢。 from yeanzhijquery
JavaScript 是一种面向对象的动态语言,它包含类型、运算符、核心对象(core objects)和方法。不过须要注意的一个主要区别是 JavaScript 不支持类,类这一律念在 JavaScript 经过对象原型(object prototype)实现。另外一个主要区别是 JavaScript 中的函数也是对象,JavaScript 容许函数在包含可执行代码的同时,能像其余对象同样被传递。程序员
1,JavaScript 采用“IEEE 754 标准定义的双精度64位格式”,也就是说不区分整形和浮点数,js中一切数字都是用浮点数表示。
2,js中算数除了+,-,*,/等常规运算符外,在Math中还定义了一些高级数学函数,在使用以前请肯定传入的参数是数字,可使用Numbetr(),parseInt(),或者parseFloat()转化成数字并用isNaN()来断定,若是返回的是数字,那么!isNaN(theNumber)将返回true。web
注意:Number()的强制类型转换与parseInt()和parseFloat()方法的处理方式类似,只是它转换的是整个值,而不是部分值。parseInt()和parseFloat()函数会尝试逐个解析字符串中的字符,直到赶上一个没法被解析成数字的字符,而后返回该字符前全部数字字符组成的数字。如“3.4.5”被转换成“3.4”,用Number()进行强制类型转换将返回NAN,同理使用运算符 + 将字符串转换成数字,只要字符串中含有没法被解析成数字的字符,该字符串都将被转换成 NaN。若是字符串值能被完整地转换,Number()将判断是调用parseInt()仍是parseFloat()。编程
JavaScript 中的字符串是一串字符序列。更准确地说,它们是一串由Unicode 字符构成的字符序列,每个字符由一个 16 位二进制数表示。浏览器
这个类型的变量有两个可能的值,分别是 true 和 false(二者都是关键字)。根据具体须要,JavaScript 按照以下规则将变量转换成布尔类型:
1,false、0、空字符串("")、NaN、null 和 undefined 被转换为 false,
2,其余值被转换为 true闭包
JavaScript 中 null 和 undefined 是不一样的,前者表示一个空值(non-value),后者是“undefined(未定义)”类型的对象,表示一个尚未被分配的值。不过undefined==null 返回的是true,也就是说在实际编程中他俩误用对代码几乎没什么影响。并发
1,在 JavaScript 中声明一个新变量的方法是使用关键字 var,
2,在js1.7中 let 关键字被引入,咱们可使用 let 语句声明一个变量,该变量的范围限于声明它的块中。 能够在声明变量时为变量赋值,也能够稍后在脚本中给变量赋值。
使用 let 声明的变量,在声明前没法使用,不然将会致使错误。
若是未在 let 语句中初始化您的变量,则将自动为其分配 JavaScript 值 undefined。编程语言
var i = 10;{ let i = 2; // 这, i = 2.}// 这里, i = 10.
经过对比let和var更有助于理解这个关键字
1,全局中使用这两个没有任何差异
let me = 'go'; //和下面等同var i = 'able';
2,函数做用域里面
function ingWithinEstablishedParameters() { let terOfRecommendation = 'awesome worker!'; var sityCheerleading = 'go!'; //没什么区别};
3,块做用域中这里是差异
function allyIlliterate() { //变量tuce 在这里不可用 for( let tuce = 0; tuce < 5; tuce++ ) { //tuce is only visible in here (and in the for() parentheses) }; //变量tuce 在这里不可用};function byE40() { //变量nish 在这里可用 for( var nish = 0; nish < 5; nish++ ) { //nish is visible to the whole function }; //变量nish 在这里可用};
4,let还能够建立本身的封闭块,固然一遍我不推荐这样
function conjunctionJunctionWhatsYour() { //变量sNotGetCrazy 在这里不可用 let( sNotGetCrazy = 'now' ) { //sNotGetCrazy is only visible in here }; //变量sNotGetCrazy 在这里不可用};
综述:主要的区别是 var 变量的范围是整个封闭函数
js很容易在全局命名空间中建立变量,定义全局变量会污染共享的命名空间,而且可能致使意外的冲突,同时全局变量不利于模块化,它会致使程序中独立的组件没必要要的耦合,在 code now and organize later 的时候可能比较方便,但优秀的程序员会不断的留意程序的结构,持续的归类相关的功能,以及分离没必要要的组件,并将这些做为编程过程当中的一部分。
js的全局命名空间也被暴露为在程序全局做用域中能够访问的全局变量,这个对象做为this的初始值,web浏览器中全局对象被绑定到全局的window变量,添加或者修改全局变量会自动的更新全局对象
这表明建立一个全局变量有两种方法
1,在全局做用域中使用 var 声明他
2,或者将其添加到全局对象中
var 声明是变量的标准声明
var 声明的变量是永久性的,不能用delete运算符删除
注意:
1,推荐使用var声明的方式,这样会比较清晰表达全局变量在程序中的影响
2,引用未绑定的变量会在运行时有错误,可是程序中给一个未绑定的变量赋值会简单的建立一个新的全局变量
说道做用域,就要提到js中的做用域链的优先级:
嵌套函数的调用对象>调用对象>全局对象
看下面的例子(声明:下面的例子摘自本人EverNote js笔记,应该是来源于互联网,在此感谢做者给出的形象例子)
eg1. var scope="global"; function f(){ alert(scope); var scope="local"; alert(scope); } f(); 过程: 建立全局对象,搜索函数外的var声明语句,在全局对象中建立scope属性,scope=undefined 建立全局的执行环境,做用域链只有一个对象:全局对象 依次执行代码: var scope="global"时,变量名解析开始,在全局对象属性中查找scope属性 把"global"赋给scope 遇到函数调用:建立调用对象 搜索函数中的var声明语句和参数,在调用对象中建立scope的属性,scope=undefined 建立函数执行环境,做用域链:调用对象>全局对象 依次执行代码: alert(scope),查询scope,变量名解析,先搜索调用对象,找到scope属性,其值为undefined,执行 var scope="local",查询scope,变量名解析,先搜索调用对象,找到scope属性,scope="local" alert(scope),查询scope,变量名解析,先搜索调用对象,找到scope属性,其值为"local",执行 eg2. var scope="global"; function f(){ alert(scope); scope="local"; alert(scope); } f(); 过程: 建立全局对象,搜索函数外的var声明语句,在全局对象中建立scope属性,scope=undefined 建立全局的执行环境,做用域链只有一个对象:全局对象 依次执行代码: var scope="global"时,变量名解析开始,在全局对象属性中查找scope属性 把"global"赋给scope 遇到函数调用:建立调用对象 搜索函数中的var声明语句和参数,没有找到var声明语句 建立函数执行环境,做用域链:调用对象>全局对象 依次执行代码: alert(scope),查询scope,变量名解析,先搜索调用对象,没找到scope属性,再搜索全局对象,找到scope属性,其值为"global"执行 scope="local",查询scope,变量名解析,先搜索调用对象,没找到scope属性,,再搜索全局对象,找到scope属性,scope="local" alert(scope),查询scope,变量名解析,先搜索调用对象,没找到scope属性,再搜索全局对象,找到scope属性,其值为"local",执行 eg3. scope1="global"; alert(scope1); function f(){ alert(scope2); scope2="local"; } f(); 过程: 建立全局对象,没有找到var声明语句,没有自定义的全局对象属性 建立全局的执行环境,做用域链只有一个对象:全局对象 依次执行代码: scope1="global"时,变量名解析开始,做用域链是没有找到scope1属性,在全局对象属性中建立scope1属性,并赋值为"global" alert(scope1)时,变量名解析开始,做用域链是找到scope1属性,其值为"global",执行 遇到函数调用:建立调用对象 搜索函数中的var声明语句和参数,没有找到var声明语句 建立函数执行环境,做用域链:调用对象>全局对象 依次执行代码: alert(scope2),查询scope2,变量名解析,做用域链是没有找到scope2属性,报错scope2 is not defined
说道做用域,就必需要提到“闭包”这个特性,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即便已经离开了创造它的环境也不例外,这就叫闭包。
在 ECMAScript 中使用全局变量是一个简单的闭包实例。
为了更好的理解闭包,咱们要记住三点:
1,js容许引用在当前函数之外定义的变量
function makeSandwith(){ var magicIngredient = "peanut butter"; return function(filling){ return magicIngredient+" and "+filling; }('jelly')}//console: peanut butter and jelly
2,即便外部函数返回,js也容许当前函数引用在外部函数所定义的变量
function makeSandwith(){ var magicIngredient = "peanut butter"; return function(filling){ console.log(magicIngredient+" and "+filling); };}var res = makeSandwith();res('jelly')res('jelly')res('jelly')
上面代码构造闭包的字面量语法叫作“函数表达式”,该函数是匿名的,咱们只须要它能产生一个新的函数值,而不打算在局部掉用它。
3,闭包能够更新外部变量的值,实际上闭包存储的是一个引用而不是副本
function box(){ var val = undefined; return{ set:function(newVal){val=newVal;}, get:function(){return val;}, type:function(){return typeof val;} }}var b = box();console.log(b.type());b.set('yeanzhi');console.log(b.get());console.log(b.type());console: undefined yeanzhi string
这个例子生成了三个闭包对象,分别是set,get,type,他们都共享val这个变量 下一篇介绍 运算符与操做符