• 1. 第5章 JavaScript高级编程
  • 2. 课程回顾Web Service具有以下优势 平台无关性 编程语言无关性 部署、升级和维护Web服务简单 对于Web服务使用者来说,可以轻易实现多种数据、多种服务的聚合 成本低 数据不受防火墙阻挡 简单对象访问协议(SOAP)是基于XML的轻量级协议,通过它,可以实现在Internet上任意位置调用已发布的Web Service WSDL与SOAP和UDDI(统一描述、发现和集成机制)一起工作,支持Web服务与Internet上的其他服务、应用程序和设备交互作用。UDDI提供了发布和定位Web服务的功能,WSDL描述了Web服务,SOAP为Web服务提供了传输消息
  • 3. 本章内容JavaScript变量作用域 JavaScript函数 JavaScript面向对象编程 JavaScript闭包 JavaScript处理JSON数据
  • 4. 本章目标深入了解JavaScript的变量作用域 能够使用JavaScript进行面向对象编程 理解JavaScript中闭包的概念和作用 理解JSON数据的格式及使用JavaScript处理JSON数据
  • 5. 1. JavaScript重点回顾1.1 数组 一个JavaScript数组的元素可以具有任意的数据类型,同一个数组的不同元素可以具有不同的类型,数组的元素设置可以包含其他数组 var a=['北京','上海',true,1,20,'深圳']; with(document) { writeln('遍历数组a的值是:'); for(var i=0;ia.length=' + a.length); writeln('
    a[2].one=' + a[2].one); writeln('
    a[2]["two"]='+a[2]["two"]); } b[true] = true; with (document){ writeln('
    b.length=' + b.length); writeln('
    b[true]=' + b[true]); writeln('
    b[6]=' + b[6]); //索引溢出,但不会出错,值是undefined } for (i in b){ document.writeln('
    b['+i+']='+b[i]); } 为数组a添加了一个元素 访问第3个元素(对象)的属性 for … in 遍历数组元素
  • 8. 数组多维数组 数组元素可以是任何类型的数据,当然可以是另一个数组,就可以非常方便地模拟多维数组 var one = new Array(3); for (var i=0;iarrayA[' + i + '][' + j + ']=' + arrayA[i][j]); } } 使用new Array()创建多维数组使用[ ]创建多维数组
  • 9. 数组数组排序 使用Array对象的sort()方法,该方法允许传递一个排序函数作为参数。如果不传递参数,则按照ASCII字符顺序升序排列 var a = new Array(10, 215, 324, 3, 1254, 300); function sortFunction(one, two){ return one - two; } a.sort(); for (i in a) {document.writeln(a[i]);} document.writeln("
    "); a.sort(sortFunction); for (i in a) {document.writeln(a[i]);} 作为sort()方法的参数传递的函数无参数,按ASCII字符顺序升序排列传递参数,按参数指定的排序规则排序
  • 10. 1.2 函数命名函数的创建和调用 函数也是一种数据类型,是function类型。所以只要使用function关键字标识一个函数名,就可以在大括号内编写代码,并且可以被调用、作为其他函数的参数或者作为对象的属性值。var n0 = factorial$(0); var n10 = factorial$(10); var n20 = factorial$(20); alert('0的阶乘为:' + n0 + '\n10的阶乘为:' + n10 + '\n20的阶乘为:' + n20);调用函数 语法: function 函数名(形参列表){ 执行语句 return 返回值;//可选的语句 } function factorial$(n) { var out=1; if (n == 0) return out; for (var i = 1; i <= n; i++) { out *= i; } return out; }创建计算阶乘的函数
  • 11. 1.2 函数函数的参数和返回值 参数名可以重复,但通过此参数名获取的值为实际传递参数的最后一个,如果实际传递参数值的个数小于重名参数的个数,那么通过此参数名获取的值为undefined 即使声明了形参,调用时也可以不传递参数 不管形参有几个,传递实参可以和形参个数不同 在函数被调用时,会创建一个arguments对象,负责管理参数 参数和返回值都可以是任何类型,包括function类型 函数可以不需要return语句来返回值,即使没有return语句,函数也会返回值,这种情况下返回值是undefined function fnArgs(){ var result = ''; for (var i = 0; i < arguments.length; i++){ result += arguments[i] + ','; } result = result.substring(0, result.length - 1); return result; } function fnReturn(){ } function fnArgsIterate(){ return a + b; } var a=5,a=6,b=7; alert('为fnArgs()传递的实参是:' + fnArgs(3, 'shanghai', 3.14) + '\n函数fnReturn()返回值是:' + fnReturn() + '\n为fnArgsInterate()传递了重复参数,结果是:' + fnArgsIterate(a, a, b));
  • 12. 1.2 函数内部函数和匿名函数 在一个函数内部,可以把另一个函数作为数据使用,这就形成了内部函数 var fn = function(){ return a+b; } var a = 10, b = 20; document.writeln(fn(a, b)+'
    ');创建一个匿名函数var func = function() { return function(){ document.writeln("函数返回值是一个内部函数
    "); } } func()(); (function() { document.writeln('创建即运行'); })(); 创建一个内部函数调用内部函数
  • 13. 小结1创建数组的方式有哪几种? 如何创建多维数组? 如何访问数组元素? 如何对数组排序
  • 14. 2.JavaScript面向对象编程2.1 对象 对象是无序属性的集合,属性可以是任何类型的值,包括其他的对象或函数,当函数作为属性值时称作“方法”,即对象的行为 常用对象的内部属性 属性类型说明prototype对象获得对象原型,用来实现继承功能class字符串描述对象类型的字符串,使用typeof操作符返回的结果get函数获取指定属性名称的属性值put函数为指定的属性赋值canPut函数指定属性是否可以通过Put进行赋值hasProperty函数是否有指定的属性delete函数删除对象指定的属性defaultValue函数返回对象的默认值construct函数对象的构造函数call函数执行关联在对象上的代码(通过函数名调用)
  • 15. 对象对象的创建、访问和释放 创建对象语法: var 对象名=new 构造函数() var s = new String(); var obj = new Object; //构造函数不需要传递参数时,可以省略括号 with (document) { writeln('s对象的构造函数为:' + s.constructor); writeln('
    Object对象的原型是:' + Object.prototype); } Number.prototype.add = function(num) { return (this + num); } document.writeln('
    Number对象扩展了一个add方法,(5).add(10)='+(5).add(10)); document.writeln('
    obj对象的构造函数的原型是:' + obj.constructor.prototype); s.address = "北京"; document.writeln("
    对象s添加了属性address,s.address=" + s.address); s["fn"] = function(a) { return a + this.address; } document.writeln("
    函数属性返回的值:s.fn('中国')=" + s.fn('中国 ')); s.address = null; s = null;创建对象使用prototype属性为Number对象扩展一个方法 为对象生成一个变量属性 为对象生成一个函数类型的属性 移除对象的属性,释放对象
  • 16. 对象常用内置对象 Global对象没有construct属性,所以无法使用new操作符构造。没有call属性,所以无法像函数一样调用。Global对象只是一个概念,表示全局对象,依据宿主不同而不同。例如,在浏览器中,window就是Global对象 var lan = 'zh'; var money = '3000'; function getLan() { var money = '5000'; var g = this == window; //this指向window //lan是window的属性,money是window的money属性,值为3000 document.writeln(g + "\n" + this.lan + "\n"+this.parseFloat(this.money)); } //getLan()是window的属性 window.getLan();所有的变量和函数都是Global对象的属性,如果有同名,则后定义的覆盖先定义思考:this.money的值是3000还是5000?
  • 17. 对象常用内置对象 Object对象是所有对象的基础,任何其他对象都是从Object对象原型扩展而来。如果为Object对象使用原型扩展了属性,则所有对象都具有此属性 Object.prototype.money = 3000; document.writeln("添加了原型属性money,值为:" + Object.money); Object.money=5000 ; document.writeln("
    生成了对象属性money,值为:" + Object.money); var s = new String(); // String也因为Object原型扩展而拥有了money属性 document.writeln("
    String对象继承了money属性,值为:" + s.money);想想看:s.money的值是3000还是5000?
  • 18. 对象常用内置对象 Function对象:当使用function关键字定义了一个函数时,在系统内部实际上时创建了一个Function对象,因为函数也是对象 函数的调用 函数名(); apply(this,函数参数数组); call(this,函数参数列表); var s= new String(); s.money = 1000;//money是String对象的属性 var money = 2000;//money是window对象的属性 var func1 = new Function("a", "b", "document.writeln(a+b);document.writeln(this.money+\"
    \");"); var func2 = function(a, b) { document.writeln(a + b); document.writeln(this.money+"
    "); } //因为没有传递对象引用,所以func1()函数中的this指向window func1(10, 20); //传递了对象s,所以func1中的this指向s func1.apply(s, [10, 20]); //传递的空引用,所以func2中的this指向了window func2.call(null, 10, 20); 使用new关键字调用构造函数创建函数对象,this指向因调用方式不同而不同
  • 19. 对象常用内置对象 Error对象可以在发生错误时作为参数传递给catch子句,也可以使用new关键字构造自定义的Error对象 try { var myerr=new Error(“自定义错误”);//自定义错误对象 throw myerr;//抛出自定义的错误对象 } catch(e){ alert(e.message);//message属性是Error对象最主要的属性 }
  • 20. 2.2 类的模拟 实体类 实体类是自定义类型,需要定义后才可以使用它创建对象。在JavaScript中没有class,但可以通过用function关键字和this关键字类定义类模板 语法:function 类名(参数1,参数2…参数n) { this.属性名=参数1; this.属性名=参数2; …… this.属性名=参数n; }function Teacher(n, s, a) { //绑定属性 this.name = n; this.sex = s; this.age = a; } //绑定行为 Teacher.prototype.getDetails=function() { document.writeln('教员的姓名:' + this.name + '
    教员的性别:' + this.sex + '
    教员的年龄:' + this.age); } //创建对象 var tea = new Teacher('Mary', '女', 25); //调用方法 tea.getDetails();function Teacher(n, s, a){ //绑定属性 this.name = n; this.sex = s; this.age = a; //判断行为是否已经定义过 if (Teacher.prototype.getDetails == undefined) { //绑定行为 Teacher.prototype.getDetails = function() { document.writeln('教员的姓名:' + this.name + '
    教员的性别:' + this.sex + '
    教员的年龄:' + this.age); } } } 直接将行为的绑定放在类定义的括号内
  • 21. 类的模拟类的继承 通过原型扩展的方式实现继承 function Person(){ this.name = "Jack"; Person.prototype.speak = function(){ document.writeln("Person类的原型扩展的方法speak被继承"); } Person.prototype.eat = function(){ document.writeln("
    Person类的原型扩展的方法eat被继承"); } } function Student() { Student.prototype.study = function() { document.writeln("
    Student类自己的方法"); } } //实现继承 Student.prototype = new Person(); //测试继承 var stu = new Student(); //继承的方法 stu.speak(); stu.eat(); //自己的方法 stu.study();
  • 22. 小结Global对象与浏览器的window对象由什么关系? apply()与call()方法有什么区别? 如何实现类的继承?
  • 23. 3. JavaScript闭包 3.1 什么是JavaScript闭包 “闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分 在函数体内定义另外的函数作为目标对象的方法函数,而这个对象的 方法函数反过来引用外层函数体中的临时变量(闭包是一种间接保持 变量值的机制)。当一个这样的内部函数在包含它们的外部函数之外 被调用时,就会形成闭包function funcTest(){ var tmpNum=100; //私有变量 //在函数funcTest内定义另外的函数作为funcTest的方法函数 function innerFuncTest(){ alert(tmpNum); //引用外层函数funcTest的临时变量tmpNum } return innerFuncTest; //返回内部函数 } //调用函数 var myFuncTest=funcTest(); myFuncTest();//弹出100 //下面的调用将失败 innerFuncTest();
  • 24. 什么是JavaScript闭包变量作用域内部函数也可以有自己的变量和函数,但其作用域只能是内部函数体内function funcTest(){ var tmpNum=100; //私有变量 //在函数funcTest内定义另外的函数作为funcTest的方法函数 function innerFuncTest() { var innerVar = 0; alert(innerVar++); alert(tmpNum++); //引用外层函数funcTest的临时变量tmpNum } return innerFuncTest; //返回内部函数 } var myFuncTest=funcTest(); myFuncTest();//弹出0后再弹出100innerVar的作用域仅限于函数innerFuncTest()内
  • 25. 什么是JavaScript闭包变量作用域内部函数可以引用全局变量或函数以及外部函数定义的变量或函数var globalVar = 0; function funcTest(){ var tmpNum=100; //私有变量 function innerFuncTest() { var innerVar = 0; alert(innerVar++);//引用内部函数变量 alert(tmpNum++); //引用外层函数funcTest的临时变量tmpNum alert(++globalVar);//引用全局变量 } return innerFuncTest; //返回内部函数 } var myFuncTest=funcTest(); myFuncTest();//弹出0、100和1
  • 26. 什么是JavaScript闭包变量作用域如果内部函数引用了位于外部函数中的变量,相当于授权该变量能够被延迟使用。因此,当外部函数调用完成后,这些变量的内存不会释放,因为闭包还引用这它们 在JavaScript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收
  • 27. 什么是JavaScript闭包变量作用域每次通过引用调用内部函数,内部函数内部的局部变量都会被重新创建 var globalVar = 0; function funcTest(){ var tmpNum=100; //私有变量 //在函数funcTest内定义另外的函数作为funcTest的方法函数 function innerFuncTest(){ var innerVar = 0; document.writeln(innerVar++ +","+tmpNum++ +","+ ++globalVar+"
    "); } return innerFuncTest; //返回内部函数 } var first=funcTest(); first(); //显示0、100和1 first(); //显示0、101和2,注意:函数的局部变量tmpNum被保存下来,没有销毁 var second = funcTest(); second(); //显示0、100和3 second(); //显示0、101和4
  • 28. 什么是JavaScript闭包闭包的使用利用闭包绑定参数为函数引用设置延时 function closureExample(msg) { return function() { alert(msg); }; } //使用闭包解决 window.onload = function() { var element = document.getElementById('closuretest'); if (element) { var good = closureExample('这个参数是由闭包绑定的'); element.onclick = function() { setTimeout(good, 3000); //延迟3秒弹出提示 } } } 通过闭包为setTimeout传入参数
  • 29. 3.2 闭包的使用闭包的使用通过对象实例方法关联函数 function associateObjWithEvent(obj, methodName){ return (function() { return obj[methodName](this); }); } function HtmlEle(elementId){ var el =document.getElementById(elementId); if (el) { el.onclick = associateObjWithEvent(this, "doOnClick"); el.onmouseover = associateObjWithEvent(this, "doMouseOver"); el.onmouseout = associateObjWithEvent(this, "doMouseOut"); } } HtmlEle.prototype.doOnClick = function(element) { alert(element); } HtmlEle.prototype.doMouseOver = function(element) { alert("鼠标移动到元素"+element.id +"上了"); } HtmlEle.prototype.doMouseOut = function(element) { alert("鼠标移出了元素" + element.id); } var div = new HtmlEle("closuretest"); //使用构造函数创建HtmlEle对象内部函数将作为一个 DOM 元素的事件处理器,this指向obj,即传入的dom元素 为HtmlEle对象扩展3个属性,每个属性的值都是函数类型
  • 30. 3.3 闭包之间的交互 当存在多个内部函数时,可能会出现意料之外的闭包。此时,假设多个内部函数(闭包)引用了同一个外部函数的变量,则内部函数共享同一个封闭环境。如果重新创建一个全局变量引用内部函数,则变量的值也重新初始化 function outerFunc() { var outerVar = 0; function innerFunc1() { document.writeln(++outerVar); } function innerFunc2() { outerVar += 5; document.writeln(","+ outerVar+"
    "); } //返回一个具有两个属性的对象 return {'innerFunc1':innerFunc1,'innerFunc2':innerFunc2}; } var globalVar = outerFunc(); globalVar.innerFunc1(); globalVar.innerFunc2(); globalVar = outerFunc(); globalVar.innerFunc1(); globalVar.innerFunc2();
  • 31. 小结闭包是什么? 举例说明闭包有哪些作用?
  • 32. 4.1 JavaScript处理JSON格式数据 4.1 JSONJSON即javascript对象标记,是一种轻量级的数据交换格式JSON的优势 同XML或HTML相比,JSON 更简单灵活 JSON是基于纯文本的数据格式,便于在网络上传入和解析 JSON的数据格式简单,但却可以传输任何类型的数据 JSON是JavaScript原生格式,在JavaScript中处理JSON数据不需要任何 特殊的 API 或工具包 { "订单编号":"OD-00001", "订单日期":"2010-1-23", "订货人":"Tom", "订单详细":[ {"商品编号":"SP-20100123", "数量":5, "单价":120, "总价":600 }, {"商品编号":"SP-20100124", "数量":50, "单价":100, "总价":5000} ] } JSON数据格式:可以是任何类型的数据,包括JavaScript对象和数组
  • 33. 4.2 JavaScript处理JSON数据 JavaScript访问JSON数据直接可以通过“.”运算符访问JSON数据的属性,也可以直接使用“=”为属性赋值function handleJSON() { var user = { "name": "Michael", "address": { "city": "Beijing", "street": " Chaoyang Road ", "postcode": 100025} }; document.write("user.name=" + user.name); document.write("
    user.address.city=" + user.address.city); } function showJSON() { var user ={"username": "Tom", "age": 20,"info": { "tel": "123456", "cellphone": "98765" }, "address":[{ "city": "beijing", "postcode": "222333" },{ "city": "newyork", "postcode": "555666" }] } with (document) { writeln("
    user.username=" + user.username); writeln("
    user.age=" + user.age); writeln("
    user.info.cellphone=" + user.info.cellphone); writeln("
    user.address[0].city=" + user.address[0].city); //address是数组 writeln("
    user.address[0].postcode=" + user.address[0].postcode); } user.username = "Jack"; document.writeln("
    user对象的username属性被重新赋值,user.username="+user.username); } handleJSON(); showJSON();取JSON对象的属性值为属性赋值
  • 34. JavaScript处理JSON数据 使用“json2.js”文件中stringify()方法将JSON对象转换为JSON字符串 使用“json2.js”文件中parse()方法将JSON格式的字符串转换为JSON数据对象 使用JavaScript的eval()方法将普通字符串转换为JSON数据对象 //声明普通字符串 var normalstring='{persons:[{name:"jordan",sex:"m",age:"40"}, {name:"bryant",sex:"m",age:"28"}]}'; //声明JSON格式的字符串 var jsontext='{"persons":[{"name":"jordan","sex":"m","age":"40"}, {"name":"bryant","sex":"m","age":"28"}]}'; var myjson = eval(normalstring); with (document) { writeln('转换后的JSON对象:' + myjson); } document.writeln('
    myjson[0].name=' + myjson[0].name); var text = JSON.stringify(myjson); document.writeln('
    转换后的json文本:' + text); var myData = JSON.parse(jsontext); document.writeln('
    转换后的JSON对象:' + myData); document.writeln('
    myjson[1].name=' + myjson[1].name);
  • 35. 小结JSON的优势有哪些? JavaScript如何解析JSON格式的数据? 如何把JSON格式的数据对象转换为字符串?
  • 36. 总结JavaScript创建数组有两种方式 使用[]创建 使用new关键字创建数组对象Array() 在JavaScript中可以创建命名函数、匿名函数和内部函数 JavaScript中函数的参数长度是不固定的,实际参数可以与形式参数的个数不同 JavaScript中对象就是无序属性的集合,对象的属性可以是任何类型的数据 JavaScript常用的内置对象 Global对象时顶级对象,在浏览器中,window对象就是Global对象 Object对象时所有对象 Function对象的构造函数可以创建函数对象 Object对象是所有对象的基础,任何其他对象都是从Object对象扩展而来 当一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。闭包可以读取函数内部的变量,让这些变量的值始终保持在内存中 JSON是一种基于文本格式的轻量级对象,使用JavaScript处理JSON数据简单、方便
  • 37. (本页无文本内容)