说明

本系列属于进阶系列,语常用语法等不在本系列介绍范围之内。

在我刚开始做一个程序员并开发项目的时候,我总是喜欢使用开发语言的各种特性,每次m$发布新版C#的时候我总是会把开发者预览版下好,亲自体验,并期望从中获得快感,每次使用新的语言进行程序设计的时候,我总是喜欢掌控他有趣的地方,尽管很多与软件工程有悖。这似乎让我出过很多风头,别人的问题似乎没有什么能难倒我的,后来在我开始从工程领域思考问题的时候,我发现很多特点给我带来的"编程快感"引发的麻烦超过了快感本身的价值,很多地方难以被同项目的人理解,这些奇淫技巧在我学习jquery源码的时候也给我带来了不小的麻烦(jq源码使用了大量js技巧),没有相比于更工程化的backbone.js的源码易于学习,这一年我学会了在中间做取舍,这是必须的。

不过我认为我快速学习的能力需要保留,我一般把我学过的高级编程语言分为“面向过程”,“面向对象”,“函数式”,“并发式”,这让我学一个新语言的时候会非常之快速,不过大多数语言都是把特点混杂在一起了。

本系列内容为本人平时项目实践和参照MDN,MSDN,《javascript语言精粹》,《Effective Javascript》等资料,并且整理自己EverNote的日常积累整理所写,时间太长有一些代码样例来源不可考。本系列不允许任何形式的转载,谢谢。 from yeanzhi

大纲

第一天:javascript变量,操作符与变量作用域

第二天:javascript函数

第三天:对象与原型

第四天:再谈函数与继承

第五天:内置对象

第六天:特殊性质与技巧

第一天:javascript变量与表达式(1)

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。

注意: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。

  1. var i = 10;
  2. {
  3. let i = 2;
  4. // 这, i = 2.
  5. }
  6. // 这里, i = 10.

通过对比let和var更有助于理解这个关键字

1,全局中使用这两个没有任何差别

  1. let me = 'go'; //和下面等同
  2. var i = 'able';

2,函数作用域里面

  1. function ingWithinEstablishedParameters() {
  2. let terOfRecommendation = 'awesome worker!';
  3. var sityCheerleading = 'go!'; //没什么区别
  4. };

3,块作用域中这里是差别

  1. function allyIlliterate() {
  2. //变量tuce 在这里不可用
  3. for( let tuce = 0; tuce < 5; tuce++ ) {
  4. //tuce is only visible in here (and in the for() parentheses)
  5. };
  6. //变量tuce 在这里不可用
  7. };
  8. function byE40() {
  9. //变量nish 在这里可用
  10. for( var nish = 0; nish < 5; nish++ ) {
  11. //nish is visible to the whole function
  12. };
  13. //变量nish 在这里可用
  14. };

4,let还可以创建自己的封闭块,当然一遍我不推荐这样

  1. function conjunctionJunctionWhatsYour() {
  2. //变量sNotGetCrazy 在这里不可用
  3. let( sNotGetCrazy = 'now' ) {
  4. //sNotGetCrazy is only visible in here
  5. };
  6. //变量sNotGetCrazy 在这里不可用
  7. };

综述:主要的区别是 var 变量的范围是整个封闭函数

变量作用域(这里不讨论1.7引入的let)

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允许引用在当前函数以外定义的变量

  1. function makeSandwith(){
  2. var magicIngredient = "peanut butter";
  3. return function(filling){
  4. return magicIngredient+" and "+filling;
  5. }('jelly')
  6. }
  7. //console: peanut butter and jelly

2,即使外部函数返回,js也允许当前函数引用在外部函数所定义的变量

  1. function makeSandwith(){
  2. var magicIngredient = "peanut butter";
  3. return function(filling){
  4. console.log(magicIngredient+" and "+filling);
  5. };
  6. }
  7. var res = makeSandwith();
  8. res('jelly')
  9. res('jelly')
  10. res('jelly')

上面代码构造闭包的字面量语法叫做“函数表达式”,该函数是匿名的,我们只需要它能产生一个新的函数值,而不打算在局部掉用它。

3,闭包可以更新外部变量的值,实际上闭包存储的是一个引用而不是副本

  1. function box(){
  2. var val = undefined;
  3. return{
  4. set:function(newVal){val=newVal;},
  5. get:function(){return val;},
  6. type:function(){return typeof val;}
  7. }
  8. }
  9. var b = box();
  10. console.log(b.type());
  11. b.set('yeanzhi');
  12. console.log(b.get());
  13. console.log(b.type());
  14. console:
  15. undefined
  16. yeanzhi
  17. string

这个例子生成了三个闭包对象,分别是set,get,type,他们都共享val这个变量

下一篇介绍 运算符与操作符

六天玩转javascript:javascript变量与表达式(1)的更多相关文章

  1. 六天玩转javascript:javascript变量与表达式(2)

    本系列内容为本人平时项目实践和参照MDN,MSDN,<javascript语言精粹>,<Effective Javascript>等资料,并且整理自己EverNote的日常积累 ...

  2. JavaScript中变量提升是语言设计缺陷

    首先纠正下,文章标题里的 “变量提升” 名词是随大流叫法,“变量提升” 改为 “标识符提升” 更准确.因为变量一般指使用 var 声明的标识符,JS 里使用 function 声明的标识符也存在提升( ...

  3. JavaScript中的函数表达式

    在JavaScript中,函数是个非常重要的对象,函数通常有三种表现形式:函数声明,函数表达式和函数构造器创建的函数. 本文中主要看看函数表达式及其相关的知识点. 函数表达式 首先,看看函数表达式的表 ...

  4. 深入理解javascript:揭秘命名函数表达式

    这是一篇转自汤姆大叔的文章:http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html 前言 网上还没用发现有人对命名函数表达式进去重复深 ...

  5. JavaScript中变量声明有var和没var的区别

    JavaScript中变量声明有var和没var的区别 JavaScript中有var和没var的区别 Js中的变量声明的作用域是以函数为单位,所以我们经常见到避免全局变量污染的方法是 (functi ...

  6. 【粗糙版】javascript的变量、数据类型、运算符、流程结构

    本文内容: javascript的变量 javascript的数据类型 javascript的运算符 javascript的流程结构 首发日期:2018-05-09 javascript的变量 创建变 ...

  7. JavaScript之变量、作用域和内存问题

    js中的变量可能包含2种数据类型,基础数据类型和引用数据类型. 一般而言,基本数据类型是数据段,引用数据类型是对象. 保存方式的不同: 基本类型可以直接操作保存在变量中的值:而引用类型真实的值是保存在 ...

  8. JavaScript的变量:变量提升

    JavaScript代码的运行规则 在JavaScript代码运行之前其实是有一个编译阶段的.编译之后才是从上到下,一行一行解释执行.这样一来也给初学者造成很大的误解.初学者会觉得JavaScript ...

  9. 关于javascript中变量及函数的提升

    javascript中变量以及函数的提升,在我们平时的项目中其实还是挺常用的,尤其是大型项目中,不知不觉就会顺手添加一些变量,而有时候自己的不小心就会酿成一些不必要错误,趁有时间整理一下自己对于js中 ...

随机推荐

  1. 深入理解JS异步编程三(promise)

    jQuery 原本写一个小动画我们可能是这样的 $('.animateEle').animate({ opacity:'.5' }, 4000,function(){ $('.animateEle2' ...

  2. 开源文档管理工具Joomla的网站安装

    1.配置PHP开发环境(Apache.PHP.MySQL) 2.安装Joomla网站: 1. 下载安装包     http://www.joomla.org/download.html 2. 登陆Jo ...

  3. Lambda 表达式的基本形式

    基本形式: (input parameters) => expression 其中:运算符“=>”读作“goes to”. 例如: () => 5 * 3; (x) => x ...

  4. a + b + c 求和

    #include <iostream> int main() { std::cout << "请输入三个数字,以空格分隔,按回车键结束:" << ...

  5. SVM3 Soft Margin SVM

    之前分为两部分讨论过SVM.第一部分讨论了线性SVM,并且针对线性不可分的数据,把原始的问题转化为对偶的SVM求解.http://www.cnblogs.com/futurehau/p/6143178 ...

  6. java io学习之File类

    1.先看下四个静态变量 static String pathSeparator The system-dependent path-separator character, represented a ...

  7. java核心知识点学习----equals和==的比较、单例模式,饿汉式,饱汉式

    最近发现自己学习能力变慢了,想来想去还是发现是因为自己Java基础没有打扎实,接下来的一系列文章将主要记录自己对于Java的最基础知识点的学习. 一.equals和==的比较 先看例子: packag ...

  8. [原创] Legato 8.1 oracle full backup skip 奇怪的问题处理过程 -- 非调度日期手工运行调度也不成功(skip)

    转载请注明出处: http://www.cnblogs.com/fengaix6/p/4677024.html 作者:飄ぺ風 环境: a. Server: Legato 8.1.2, aix 6.1 ...

  9. Wpf 中使用gif格式的动态图

    第一种方法:使用winform插件 <WindowsFormsHost  xmlns:wf="clr-namespace:System.Windows.Forms;assembly=S ...

  10. 命令行参数 main()函数设计

    一.main()函数的形式 int main( void )--无参数形式 { ... return 0; } int main( int argc, char *argv[] )--带参数形式 { ...