JavaScript面试后的反思.doc_第1页
JavaScript面试后的反思.doc_第2页
JavaScript面试后的反思.doc_第3页
JavaScript面试后的反思.doc_第4页
JavaScript面试后的反思.doc_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

JavaScript面试后的反思(1)2012-07-06 13:54 nowamagic MXRIA 我要评论(0) 字号:T | T为什么这么说,前些日子收到面试邀请,那就去试试呗,有几年没有面试过了吧。和面试官坐在沙发上,聊天式的他问我答,以下就是几个javascript方面的问题。AD: 2013云计算架构师峰会精彩课程曝光 写此文目的是为了让更多的程序员理解javascript的一些概念,对,是理解,而不是了解。我们已经了解得够多了,该是向深入理解的方向靠拢的时候了。为什么这么说,前些日子收到面试邀请,那就去试试呗,有几年没有面试过了吧。和面试官坐在沙发上,聊天式的他问我答,以下就是几个javascript方面的问题:请创建一个对象,包括几个公有属性,接下来是为对象创建一个公有方法,然后为对象创建几个私有属性,一个私有方法。说实话,这几个问题我默名其妙,要是他让我用jquery写个拖动插件什么的,我估计我能写挺好,原生的javascript,晕,虽然我看过jquery源码解读,但这些基本概念要命。本文的例子输出使用如下方法,便于查看:1. function dwn(s)document.write(s+); function从一开始接触到js就感觉好灵活,每个人的写法都不一样,比如一个function就有N种写法,如:1. function showMsg() 2. var showMsg = function() 3. showMsg = function() 似乎没有什么区别,都是一样的嘛,真的是一样的吗,大家看看下面的例子:1. /- 2. /函数定义:命名函数(声明式),匿名函数(引用式) 3. /声明式,定义代码先于函数执行代码被解析 4. function t1()dwn(t1); 5. t1(); 6. function t1() 7. dwn(new t1); 8. t1();/引用式,在函数运行中进行动态解析 9. var t1 = function() dwn(new new t1); 10. t1(); 11. var t1 = function() 12. dwn(new new new t1); 13. t1();/以上输出:new t1,new t1,new new t1,new new new t1 可能想着应该是输出t1,new t1,new newt1,new new new t1,结果却并不是这样,应该理解这句话:声明式,定义代码先于函数执行代码被解析。如果深入一步,应该说是scope链问题,实际上前面两个方法等价于window.t1,可以理解为t1是window的一个公有属性,被赋了两次值,以最后一次赋值为最终值。而后面两个方法,可以理解为是t1是个变量,第四个方法的var去掉之后的结果仍然不会改变。然而,当第四个方法改成function t1()这样的声明式时,结果变成了new new new t1,new new new t1,new new t1,new new t1前面两个按照我的理解可以很好的理解为什么是这个答案,第三个也可以理解,但是最后一个输出让我比较纠结。另外匿名函数还有(function().)()这样的写法,最后一个括号用于参数输入。还有var t1=new function().这样的声明,实际上t1已经是一个对象了。1. var t2 = new function() 2. var temp = 100; /私有成员 3. this.temp = 200; /公有成员,这两个概念会在第三点以后展开说明 4. return temp + this.temp; 5. alert(typeof(t2); /object 6. alert(t2.constructor(); /300 除此之外,还有使用系统内置函数对象来构建一个函数,例:1. /这个位置加不加new结果都一样,WHY 2. var t3 = new Function(var temp = 100; 3. this.temp = 200; 4. return temp + this.temp;); 5. alert(typeof(t3); /function 6. alert(t3(); /300 创建对象首先我们理解一下面向对象编程(Object-Oriented Programming,OOP),使用OOP技术,常常要使用许多代码模块,每个模块都提供特定的功能,每个模块都是孤立的,甚至与其它模块完全独立。这种模块化编程方法提供了非常大的多样性,大大增加了代码的重用机会。可以举例进一步说明这个问题,假定计算机上的一个高性能应用程序是一辆一流赛车。如果使用传统的编程技巧,这辆赛车就是一个单元。如果要改进该车,就必须替换整个单元,把它送回厂商,让汽车专家升级它,或者购买一个新车。如果使用OOP技术,就只需从厂商处购买新的引擎,自己按照说明替换它,而不必用钢锯切割车体。不过大部分的论点是,javascript并不是直接的面向对象的语言,但是通过模拟可以做到很多面向对象语言才能做到的事,如继承,多态,封装,javascript都能干(没有做不到,只是想不到):1. /- 2. /以下三种构造对象的方法 3. /new Object,实例化一个Object 4. var a = new Object(); 5. a.x=1, a.y=2;/对象直接量 6. var b = x:1,y:2;/定义类型 7. function Point(x,y) /类似于C#中的类 8. this.x=x; 9. this.y=y; 10. var p = new Point(1,2); /实例化类 第一种方法通过构造基本对象直接添加属性的方法来实现,第二种和第一种差不多,可以看成是第一种方法的快捷表示法。第三种方法中,可以以类为基础,创造多个类型相同的对象。对象属性的封装(公有和私有)以例子来说明:1. function List() 2. /私有成员,在对象外无法访问,如果此处无var声明,则m_elements将变成全局变量,这样外部是可以直接访问到的,如 3. alert(m_elements0) 4. var m_elements=; 5. m_elements=Array.apply(m_elements,arguments); /此处模拟getter,使用时alist.length; 6. /等价于getName()方式: 7. this.length=function() 8. return m_elements.length;,/使用时alist.length(); 9. /公有属性,可以通过.运算符或下标来访问 10. this.length = valueOf:function() return m_elements.length; , 11. toString:function() 12. return m_elements.length; 13. /公有方法,此方法使用得alert(alist)相当于 14. alert(alist.toString() 15. this.toString=function() 16. return m_elements.toString(); 17. /公有方法 18. this.add=function() 19. m_elements.push.apply(m_elements,arguments); 20. /私有方法如下形式,这里涉及到了闭包的概念,接下来继续说明 21. /var add=function()或function add() 22. /m_elements.push.apply(m_elements,arguments);/ 23. var alist=new List(1,2,3);dwn(alist); 24. /=alert(alist.toString(),输出1,2,3 25. dwn(alist.length); /输出3a 26. list.add(4,5,6); 27. dwn(alist); /输出1,2,3,4,5,6 28. dwn(alist.length); /输出6 属性和方法的类型javascript里,对象的属性和方法支持4种不同的类型:private property(私有属性),dynamic public property(动态公有属性),static public property/prototype property(静态公有属性或原型属性),static property(静态属性或类属性)。私有属性对外界完全不具备访问性,可以通过内部的getter和setter(都是模拟);动态公有属性外界可以访问,每个对象实例持有一个副本,不会相互影响;原型属性每个对象实例共享唯一副本;类属性不作为实例的属性,只作为类的属性。以下是例子:1. /- 2. /动态公有类型,静态公有类型(原型属性) 3. function myClass() 4. var p=100; /private property 5. this.x=10; /dynamic public property 6. 7. myCtotype.y=20; /static public property or prototype property, 1. /要想成为高级javascript阶段,prototype和闭包必须得理解和适当应用 2. myClass.z=30; /static property 3. var a=new myClass(); 4. dwn(a.p) /undefined 5. dwn(a.x) /10 6. dwn(a.y) /20 7. a.x=20; 8. a.y=40; 9. dwn(a.x); /20 10. dwn(a.y); /40 11. delete(a.x); /删除对象a的属性x 12. delete(a.y); /删除对象a的属性y 13. dwn(a.x); /undefined 14. dwn(a.y); /20 静态公有属性y被删除后还原为原型属性y 15. dwn(a.z); /undefined 类属性无法通过对象访问 16. dwn(myClass.z); 原型(prototype)这里只讲部分,prototype和闭包都不是几句话都能讲清楚的,如果这里可以给你一些启蒙,则万幸矣。习语照猫画虎,这里的猫就是原型,虎是类型,可以表示成:虎.prototype=某只猫 or 虎.prototype=new 猫()。因为原型属性每个对象实例共享唯一副本,所以当实例中的一个调整了一个原型属性的值时,所有实例调用这个属性时都将发生变化,这点需要注意。以下是原型关系的类型链:1. function ClassA() 2. ClassA.prototype=new Object(); 3. function ClassB() 4. ClassB.prototype=new ClassA(); 5. function ClassC() 6. ClassC.prototype=new ClassB(); 7. var obj=new ClassC(); 8. dwn(obj instanceof ClassC); /true 9. dwn(obj instanceof ClassB); /true 10. dwn(obj instanceof ClassA); /true 11. dwn(obj instanceof Object); /true 12. /带默认值的Point对象: 13. function Point2(x,y) 14. if (x) 15. this.x=x; 16. if (y) 17. this.y=y;/设定Point2对象的x,y默认值为0 18. Ptotype.x=0; 19. Ptotype.y=0;/p1是一个默认(0,0)的对象 20. var p1=new Point2(); /可以写成var p1=new Point2也不会出错,WHY 21. /p2赋值 22. var p2=new Point2(1,2); 23. dwn(p1.x+,+p1.y); /0,0 24. dwn(p2.x+,+p2.y); /1,2delete对象的属性后,原型属性将回到初始化的状态: 25. function ClassD() 26. this.a=100; 27. this.b=200; 28. this.c=300 29. ClassD.prototype = new ClassD(); /将ClassD原有的属性设为原型,包括其值 30. ClassD.prototype.reset = function() /将非原型属性删除 31. for (var each in this) 32. delete thiseach; 33. var d = new ClassD(); 34. dwn(d.a); /100 35. d.a*=2; 36. d.b*=2; 37. d.c*=2; 38. dwn(d.a); /200 39. dwn(d.b); /400 40. dwn(d.c); /600 41. d.reset(); /删掉非原型属性,所有回来原型 42. dwn(d.a); /100 43. dwn(d.b); /200 44. dwn(d.c); /300 继承如果两个类都是同一个实例的类型,那么它们之间存在着某种关系,我们把同一个实例的类型之间的泛化关系称为继承。C#和JAVA中都有这个,具体的理解就不说了。在javascript中,并不直接从方法上支持继承,但是就像前面说的,可以模拟。方法可以归纳为四种:构造继承法,原型继承法,实例继承法和拷贝继承法。融会贯通之后,还有混合继续法,这是什么法,就是前面四种挑几种混着来以下例子涉及到了apply,call和一些Array的用法:构造继续法例子1. /定义一个Collection类型 2. function Collection(size) 3. this.size = function() 4. return size; /公有方法,可以被继承 5. 6. Ctotype.isEmpty = function() /静态方法,不能被继承 7. return this.size() = 0; 8. /定义一个ArrayList类型,它继承Collection类型 9. function ArrayList() 10. var m_elements = ; /私有成员,不能被继承 11. m_elements = Array.apply(m_elements, arguments);/ArrayList类型继承Collection 12. this.base = Collection; 13. this.base.call(this, m_elements.length); 14. this.add = function() 15. return m_elements.push.apply(m_elements, arguments); 16. 17. this.toArray = function() 18. return m_elements; 19. ArrayLtotype.toString = function() 20. return this.toArray().toString(); 21. 22. /定义一个SortedList类型,它继承ArrayList类型 23. function SortedList() 24. /SortedList类型继承ArrayList 25. this.base = ArrayList; 26. this.base.apply(this, arguments); 27. this.sort = function() 28. var arr = this.toArray(); 29. arr.sort.apply(arr, arguments); 30. /构造一个ArrayList 31. var a = new ArrayList(1,2,3); 32. dwn(a); 33. dwn(a.size(); /a从Collection继承了size()方法 34. dwn(a.isEmpty); /但是a没有继承到isEmpty()方法 35. /构造一个SortedLis 36. tvar b = new SortedList(3,1,2); 37. b.add(4,0); /b 从ArrayList继承了add()方法 38. dwn(b.toArray(); /b 从ArrayList继承了toArray()方法 39. b.sort(); /b 自己实现的sort()方法 40. dwn(b.toArray(); 41. dwn(b); 42. dwn(b.size(); /b从Collection继承了size()方法 原型继承法例子1. /定义一个Point类型 2. function Point(dimension) 3. 4. this.dimension = dimension;/定义一个Point2D类型,继承Point类型 5. 6. 7. function Point2D(x, y) 8. 9. this.x = x; 10. this.y = y; 11. Point2D.prototype.distance = function() 12. return Math.sqrt(this.x * this.x + this.y * this.y); 13. Point2D.prototype = new Point(2); /Point2D继承了Point 14. /定义一个Point3D类型,也继承Point类型 15. function Point3D(x, y, z) 16. this.x = x; 17. this.y = y; 18. this.z = z; 19. Point3D.prototype = new Point(3); /Point3D也继承了Point 20. /构造一个Point2D对象 21. var p1 = new Point2D(0,0);/构造一个Point3D对象 22. var p2 = new Point3D(0,1,2); 23. dwn(p1.dimension); 24. dwn(p2.dimension); 25. dwn(p1 instanceof Point2D); /p1 是一个 Point2D 26. dwn(p1 instanceof Point); /p1 也是一个 Point 27. dwn(p2 instanceof Point); /p2 是一个Point 以上两种方法是最常用的。实例继承法例子在说此法例子之前,说说构造继承法的局限,如下:1. function MyDate() 2. this.base = Date; 3. this.base.apply(this, arguments); 4. 5. var date = new MyDate(); 6. /undefined,date并没有继承到Date类型,所以没有toGMTString方法 7. alert(date.toGMTString); 核心对象的某些方法不能被构造继承,原因是核心对象并不像我们自定义的一般对象那样在构造函数里进行赋值或初始化操作换成原型继承法呢?,如下:1. function MyDate() 2. MyDtotype=new Date(); 3. var date=new MyDate(); 4. /object不是日期对象,仍然没有继承到Date类型! 5. alert(date.toGMTString); 现在,换成实例继承法:1. function MyDate() 2. /instance是一个新创建的日期对象 3. var i

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论