首页 > 代码库 > 前端学习实践笔记--JavaScript深入【1】
前端学习实践笔记--JavaScript深入【1】
这一年中零零散散看过几本javascript的书,回过头看之前写过的javascript学习笔记,未免有点汗颜,突出“肤浅”二字,然越深入越觉得javascript的博大精深,有种只缘身在此山中的感觉,茫茫然而不得其要领,索性在一边写博文中,求得突破,乃至更上一层楼。
看过的书籍推荐:
《javascript语言精粹》 Douglas Crockford
《javascript设计模式》 Addy Osmani
《javascript设计模式》 Ross Harmes
《悟透javascript》 李战
《javascript语言精髓与编程实践》 周爱民
这些书是在绝大部分javascript书籍中较好的几本了,市面上的javascript,不得不说,水分太多,养分太少。很多书翻几页也就困了。反倒是网上有些不错的博客,博客园里面,博客园的知识库里面,还有一些其他的个人博客,都是挺不错的,但是大多都比较分散,知识点也比较散落。另外由于随着javascript本身的更新,还有jQuery,YUI等一系列插件的出现,NodeJS兴起等等的影响,不同浏览器的更新以及兼容性问题,导致了原生JS的逐渐冷落,但是不管怎么说,也遮不住JS这门语言本身的魅力。
JS有很多深邃的地方值得学习,接下来着重介绍一些比较好玩的东西,这些也是我看了很多的书和博文累积起来的,但是最好的读者是稍微有点JS基础了,因为我讲的东西可能会有点跳跃,不是基础的教程。
不讲解那些复杂拗口的语法,或者那些深坑,或者那些晦涩难懂的设计模式,通过简单的实例来学习实践区分静态语言和动态语言的区别于共同点
楼主是一个记性很差,特别怕麻烦的人,楼主忠于且坚信用最简单的技术实现用户需求,能抓老鼠的猫才是猫的原则,反对过分追求优化,追求复杂的设计模式。
只求能干净的实现我的功能。主要分以下几点来讲解:
1. var 变量 声明 函数声明 提前
2. call apply的使用
3. new 实例化,复制,引用的区别
4. 原型链的使用
5. 闭包保持用户状态
6. 面向对象的实现,继承
7. this指针
8. 数组,对象,json
9. AMD,CMD简介
10. js中的深坑
11. 继续深入方向
1. var 变量 声明 函数声明提前
提到变量/函数声明,理解一个核心,JS的解析和执行时分开的,了解了这个,很多问题和怪事就都明白了。
JS代码在执行的时候,会经过两个步骤,首先是解析(预编译),然后再执行。解析就是声明变量,还没有赋值,所以是undefined的,到了具体执行的时候才会给予具体的值。要把一条赋值语句分成两部分看,例如var a = 5; 应该是 var a; a = 5;这样两部分看,复杂的情况如下几个例子:
/** * 变量声明和函数表达式(我更觉得应该叫定义,但是大家好像默认都是声明了) * 都是用var来声明,所以如果将函数具体内容看做是一个值得话,跟变量赋值其实是一回事 * 下面语句执行的顺序如下: * 首先进行变量声明,即var f;所以第一个输出时undefined * 因为有两个var f的定义,之后的定义覆盖之前的定义,所以第二个输出时25 * 第三个输出时f函数的具体内容 * 如果将var f = 0; 和var f = function(x){return x*x;}顺序倒过来,那第二个输出就要报错了, * 第三个输出是0 * *///console.log(f);//var f = 0;//var f = function(x){// return x*x;//}//console.log(f(5));//console.log(f);/** * 变量声明和函数声明 * 下面语句的执行输出结果如下: * 第一个输出是函数的具体内容 * 第二个输出是16, * 第三个输出是0 * 问题在于从技术上说,function语句并非是一个语句. * JS中语句会引发动态的行为, * 但是函数定义描述的却是静态的程序结构。 * 语句是在运行时执行的,而函数则是实际运行之前, * 当JS代码被解析或被编译时定义的。 * 当JS解析程序遇到一个函数定义时,它就解析并存储构成函数主体的语句, * 然后定义一个和该函数同名的属性 * (如果函数定义在其它的函数中,那么就在调用对象中定义这个属性, * 否则在全局对象中定义这个属性)以保存它。这会产生一些奇怪的行为。 * 总结来说就是函数声明优于比变量声明。 */console.log(f);console.log(f(4));function f(x){ return x*x;}var f = 0;console.log(f);
事实上,js的解析器对函数声明与函数表达式并不是一视同仁地对待的。对于函数声明,js解析器会优先读取,确保在所有代码执行之前声明已经被解析,而函数表达式,如同定义其它基本类型的变量一样,只在执行到某一句时也会对其进行解析,所以在实际中,它们还是会有差异的,具体表现在,当使用函数声明的形式来定义函数时,可将调用语句写在函数声明之前,而后者,这样做的话会报错。
2. call apply的使用
1、方法定义
call方法:
语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]])
定义:调用一个对象的一个方法,以另一个对象替换当前对象。
说明:
call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。
如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。
apply方法:
语法:apply([thisObj[,argArray]])
定义:应用某一对象的一个方法,用另一个对象替换当前对象。
说明:
如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。
如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。
简单来说,区别就是apply方法后面传递的参数是数组,而call方法是add.call(doubleAdd,a,b,c)形式的. 具体执行的方法看call、apply前面的函数,
如果没有提供thisObj,相当于Global。
具体来说,看几个例子:
function add(a,b){ alert(a+b);}function sub(a,b){ alert(a-b);}add.call(sub,3,1); //== add.call(null,3,1);//输出4
sub.call(null,3,1);
//输出2
//这里稍微涉及到this指针,this指向的是运行时的上下文function Class1(){ this.name = "class1"; this.showNam = function() { alert(this.name); } this.detail = "hello-1"; this.showDetail = function(){ alert(this.detail); }}function Class2(){ this.name = "class2"; this.detail = "hello-2"; this.showDetail = function(){ alert(this.detail); }}var c1 = new Class1();var c2 = new Class2();c1.showNam.call(c2);c1.showNam();c1.showDetail();c2.showDetail();// class2// class1//hello-1//hello-2
还可以用call实现继承,具体例子就不给出了,参考文章JS中的call()和apply()方法 ...里面写的很详细,该说的也都说了。
3. new 实例化,复制,引用的区别
记住function有对象化能力,体现在使用new上。如果没有使用new新创建一个对象(即复制一份相同内容), 即还是引用,对函数内部变量的改变会导致其他引用值的改变。
这里涉及到对象的概念,统一在对象的时候再说吧。。今天就写到这里了。
以上全部都属个人原创,请大家转载的时候附上原创链接: http://www.cnblogs.com/tonylp
前端学习实践笔记--JavaScript深入【1】