Javascript进阶
- 函数
- 函数申明
普通的声明 function func(m,n){alert(m+n)} func(1,5)
使用变量声明 var func=function(m,n){alert(m+n)} func(3,4)
使用构造函数声明 var func=new Function(‘m’,’n’,’alert(m+n)’) func(3,5)
- 函数作为参数
function func(x){return x*x}
function test1(x,u){return x+u(x)} alert(test1(10,func)) //将有参函数作为参数
function test2(x,u){return x+u} alert(test2(10,func(10))) //使用函数返回值作为函数参数
- 函数内部属性
arguments.length返回调用函数时传递的参数个数
test.length返回定义函数时的参数个数
在函数外部使用this,this指向window对象,全局变量可以看做window对象的属性
在函数内部使用this,this指向window对象
var x=1 function test(){var x=0;alert(x);alert(this.x)} //结果:0和1
用new来创建对象来调用属性,this指向创建的对象obj
function test(){this.x=100} var obj=new test() alert(obj.x) //结果:100
函数作为某个对象的方法被调用,this指向对象obj
function test(){alert(this.x)} var obj={} obj.x=1000 obj.m=test obj.m() //x为obj的属性,m为obj的方法,
事件监听函数中的this,this指向触发事件的元素
- 函数的属性和方法
apply和call用法一样,通常用来扩充函数运行的作用域,而非单纯的传递参数
function sum(num1,num2){return num1+num2}
function applysum(num1,num2){return sum.apply(this,[num1,num2])} alert(applysum(10,20)) //结果:30
function applysum(num1,num2){return sum.apply(this,arguments)} alert(applysum(10,20)) //结果:30
function callsum(num1,num2){return sum.call(this,num1,num2)} alert(callsum(20,30)) //结果:50
扩充函数作用域
var color=”red” var obj={color : ”blue”} function saycolor(){alert(this.color)}
saycolor() saycolor.call(this) saycolor.call(window) //结果:red
saycolor.call(obj) //结果:blue
- 变量和作用域
引用传递,person1和person2指向同一个栈内存的空间地址
var person1=new Object() person1.name=”张三” var person2=person1 alert(person1.name+person2.name) //结果:张三张三
person2.name=”李四” alert(person1.name+person2.name) //结果:李四李四
函数的参数传递都是值传递
在函数内声明变量没有用var就是全局变量
内部环境可以访问所有的外部环境,但是外部环境不能访问内部环境中的任何变量和函数
在变量的查询中,访问局部变量要比全局变量快
- JS内存管理注意事项
避免不必要的定义全局变量
及时解除不再使用的变量引用,即将其赋值为null
合理使用函数,函数中的局部变量在函数执行结束后自动释放内存
- 全局函数
parseInt()函数解析一个字符串并返回一个整数
parseFloat()函数解析一个字符串并返回一个浮点数
isNaN()函数用于检查其参数是否为非数字值
String()函数把对象的值转换成字符串
Number()函数把对象的值转换成数字
eval()函数可计算某个字符串并执行其中的代码
var str=”x=10;y=20;alert(x*y)” eval(str)
escape()函数对字符串(除了字母、数字和符号*@-_+./)进行编码,转换成十六进制
unescape()函数对字符串进行解码
encodeURI()函数把字符串编码为URI,decodeURI()函数解码
encodeURIComponent()函数把字符串编码为URI组件,decodeURIComponent()函数解码一个编码的URI组件
- confirm()弹出带有确认和取消按钮的对话框,点确定返回true,点取消返回false
function del(){ if(confirm(“确定要删除吗?”)) {alert(“已经删除”)}
else{alert(“已经取消了操作”)}}
- 动态添加元素
var i=0 function addinput(){var o=document.createElement(“input”) o.type=”button”
o.addEventListener(“click”,addinput) o.value=”按钮”+ i++ document.body.appendChild(o) o=null}
- 动态添加事件
<input id=”button1” type=”button” value=”被添加事件的按钮”>
<input id=”button2” type=”button” value=”触发添加事件的按钮” οnclick=”addclick(button1)”>
function addclick(obj){obj.οnclick=function(){alert(“动态添加事件成功”)}}
- 防止数据重复提交
readyState属性返回当前文档的状态,返回值如下:
uninitialized—还未开始载入 loading—载入中 interactive—已加载 complete—载入完成
- JavaScript面向对象
- 创建对象
普通方法(每创建一个对象都要重复对每一个属性方法赋值,复杂繁琐)
var people=new Object() people.name=’孙悟空’ people.weapon=’金箍棒’
people.run=function(){return this.name+’的武器是’+this.weapon} alert(people.run())
工厂模式(每创建一个对象都占用一个地址空间的内存,造成资源浪费,对象之间没有直接联系)
function createpeople(name,weapon){var people=new Object() people.name=name people.weapon=weapon
people.run=function(){return this.name+’的武器是’+this.weapon} return people}
var wukong=createpeople(‘孙悟空’,’金箍棒’) alert(wukong.run())
构造函数模式(使用new关键字创建对象,每创建一个对象都占用一个地址空间的内存)
function people(name,weapon){this.name=name this.weapon=weapon
this.run=function(){return this.name+’的武器是’+this.weapon}}
var wukong=new people(‘孙悟空’,’金箍棒’) alert(wukong.run())
alert(wukong instanceof People) //判断wukong是否是由People创建的对象
var monster=new Object() People.call(monster,’妖怪’,’葫芦’) alert(monster.run()) //对象冒充
原型模式(Prototype模式,创建的对象都共用一个内存地址,节约了内存,构造函数没有参数不能通过参数传递给属性赋值,所有对象共用一个内存,改变一个对象的属性所有属性值都会同时改变)
function people(){}
people.prototype={constructor:people //原型字面量方式会将对象的constructor变为object,要强制转换成people
name:’孙悟空’ weapon:’金箍棒’ run:function(){return this.name+’的武器是’+this.weapon}}
var wukong=new people() var wujing=new people() alert(wukong.run()) //wukong和wujing指向同一个地址
alert(people.prototype.isPrototypeOf(wukong)) //判断wukong是否是由People创建的对象
wukong.job=[] alert(wukong.hasOwnProperty(“job”) //判断job属性是否是本地属性,结果为true
alert(wukong.hasOwnProperty(“name”) //结果为false,name是继承的属性
alert(“name” in wukong) //判断wukong对象是否有name属性
构造函数和原型组合模式(用构造函数模式定义属性,用原型模式定义方法,既共享了同一个内存也可以通过参数给属性赋值)
function people(name,arr){this.name=name this.job=arr}
people.prototype={run:function(){return this.name+’的工作是’+this.job}}
var wukong=new people(‘孙悟空’,[’西天取经’,’保护师父’]) alert(wukong.run())
动态原型方法(方法和属性在同一个函数当中,整体性较强)
function people(name,arr){this.name=name this.job=arr if(type this.run!=”function”) //避免每次创建对象就重复初始化方法
people.prototype.run=function(){return this.name+’的工作是’+this.job}}
var wukong=new people(‘孙悟空’,[’西天取经’,’保护师父’]) alert(wukong.run())
- 继承(父类也叫超类、基类,子类也叫子类型、派生类)
使用对象冒充继承基类(构造函数绑定,用call或者apply方法,实质上改变了this的指向,每创建一个对象占用一个内存空间)
function monkey(_type,_home){this.type=_type this.home=_home}
function magicmonkey(_type,_home,_skill){monkey.call(this,_type,_home) this.skill=_skill}
var wukong=new magicmonkey(‘金丝猴’,’花果山’,[‘筋斗云’,’七十二变’]) alert(wukong.type) alert(wukong.home) //子类创建的对象可以访问父类的属性方法,子类可以多重继承多个父类
原型链继承(创建的对象都占用同一个内存,但是不支持多重继承)
function monkey(){} monkey.prototye.type=’猴子’ momkey.prototype.say=function(){alert(‘我是快乐的猴子’)}
function magicmonkey(){} magicmoney.prototype=new monkey() //将子类的prototype对象指向父类的一个实例
var wukong=new magicmoney() alert(wukong.type) alert(wukong.say)
混合模式(对象冒充继承属性,原型链继承方法)
function monkey(_type,_home){this.type=_type this.home=_home}
momkey.prototype.say=function(){alert(‘我是’+this.type+’住在’+this.home)}
function magicmonkey(_type,_home,_skill){monkey.call(this,_type,_home) this.skill=_skill} //用对象冒充继承属性
magicmoney.prototype=new monkey() //用原型链继承方法
momkey.prototype.say=function(){alert(‘我是’+this.type+’住在’+this.home+’我会’+this.skill)} //子类可以覆盖父类的方法
var wukong=new magicmonkey(‘金丝猴’,’花果山’,[‘筋斗云’,’七十二变’]) wukong.say()
- 实战练习
练习1.具有默认值的构造函数
function func(name,weapon){this.name=name if(weapon==undefined){this.weapon=’金箍棒’} else{this.weapon=weapon}}
function func(name,weapon){this.name=name this.weapon=weapon?weapon:’金箍棒’}
练习2.遍历对象的属性和方法
function func(name,weapon){this.name=name this.weapon=weapon?weapon:’金箍棒’
this.skill=function(){alert(this.name+’的武器是’+this.weapon)}}
var user=new func(‘猪八戒’,’钉耙’) for(var i in user){alert(i+’:’+user[i]+’ ‘)}
//结果:name:猪八戒 weapon:钉耙 skill: function(){alert(this.name+’的武器是’+this.weapon)}}
- 匿名函数与闭包
- 匿名函数
将函数赋值给变量通过变量调用函数 var fn=function(){alert(‘我是匿名函数’)} fn()
函数通过表达式自我执行 (function(){alert(‘我是匿名函数’)})()
匿名函数传递参数 (function(m,n){alert(m+n)})(100,1000)
- 闭包
闭包可以将局部变量存储在内存中,实现变量累加,避免了使用全局变量
function add(){var num=100 return function(){num++ alert(num)}}
var fn=add() fn() fn() fn() fn=null //通过变量赋值调用匿名函数,结果:100 101 102
add()() add()() add()() //直接自我执行,每调用一次都会初始化变量num=100,结果:100 100 100
循环函数中的匿名函数与闭包,每执行一次循环函数匿名函数就立刻自我执行一次,保证了i的同步变化
function func(){var arr=[] for(var i=0;i<5;i++){arr[i]=(function(){return ‘元素’+i})()} return arr}
var element=func() alert(element) //结果:元素0,元素1,元素2,元素3,元素4
通过参数传递而不是自我执行来同步i的值
function func(){var arr=[] for(var i=0;i<5;i++){arr[i]=function(n){return ‘元素’+n}(i)} return arr}
var element=func() alert(element) //结果:元素0,元素1,元素2,元素3,元素4
- 闭包中的this(匿名函数的执行环境具有全局性,this通常指向window)
var name=’window obj’ var obj={name:’my obj’ get:function(){return function(){return this.name }}} alert(obj.get()()) //结果:window obj alert(obj.get().call(obj)) //结果:my obj
var name=’window obj’ var obj={name:’my obj’ get:function(){var self=this return function(){
return slef.name }}} alert(obj.get()()) //结果:my obj
- 模仿块级作用域(JS中没有块级作用域的概念,这意味着在块语句,比如for循环语句中,定义的变量不会因为离开了for循环就失效,使用块级作用域匿名函数中的变量都会在执行结束后被销毁)
function func(){(function(){for(var i=0;i<3;i++){alert(i)}})() alert(i)} func() //alert(i)没起作用
function func(){return function(){for(var i=0;i<3;i++){alert(i)} alert(i)}} func()() // alert(i)输出3
- 私有变量
在函数外部不能通过对象直接调用私有变量和方法
function people(){var name=’孙悟空’ function say(){return ‘我是孙悟空’}}
var p=new people() alert(p.name) alert(p.say()) //无结果
通过构造方法传递参数来访问私有变量
function people(_name){var name=_name function say(){return ‘我是孙悟空’}
this.getname=function(){return name} this.getsay=function(){return say()}}
var p=new people(‘孙悟空’) alert(p.getname()) alert(getsay())
- 静态私有变量(所有实例共享静态私有变量)
(function(){var name=’孙悟空’ user=function(){} user.prototype.getname=function(){return name}
user.prototype.setname=function(value){name=value}})()
var p=new user() alert(p.getname()) p.setname(‘猪八戒’) alert(p.getname())//结果:孙悟空 猪八戒
var q=new user() alert(q.getname()) //结果:猪八戒
- Cookie
- 什么是cookie
Cookie是存储于访问者的计算机中的变量,每当同一台计算机通过浏览器请求某个页面时,就会发送这个cookie,当用户下一次访问同一个页面时,服务器会先查看有没有上传的cookie资料,如果有就根据cookie里的资料判断访问者,发送特定的页面内容,常见应用:自动登录、记住用户名。
- 创建cookie(Chrome只能再服务器运行环境下进行)
document.cookie=’name=张三’
可选参数expires设置cookie的过期时间,默认是会话结束时,设置为过去的时间是删除cookie操作
var day=new Date() day.setDate(day.getDate()+7) document.cookie=’name=张三;expires=’+day
可选参数path指定了与cookie关联在一起的网页,默认值是在同一目录的网页都可访问该cookie,把path设置为‘/’该网站下的所有网页可访问,一般情况下使用默认值即可
可选参数domain设定cookie的有效域名,默认值为绑定当前域名,本地测试无效
可选参数secure指定了网络上如何传输cookie,默认为普通http协议传输
- 封装cookie的操作函数
function setcookie(key,value,expires){ var day=new Date() day.setDate(day.getDate()+expires)
document.cookie=key+‘=’+value+‘;expires=’+day} setcookie(‘name’,’张三’,10)
- 读取cookie
function getcookie(name){var arrstr=doucument.cookie.split(‘; ’) //注意分号后的空格
for(var i=0;i<arrstr.length;i++){var arr=arrstr[i].split(‘=’) if(arr[0]==name) return(arr[1])} return ‘’}
alert(getcookie(‘name’)) alert(getcookie(‘email’)) //读取cookie
function removecookie(name){setcookie(name,‘随意值’,-1)} removecookie(‘name’) //删除cookie
- JSON
- 什么是JSON
JSON是存储和交换文本信息的语法,类似XML;是轻量级的文本数据交换格式;独立于语言;具有自我描述性,更容易理解;JSON是在AJAX中替代XML交换数据的最佳方案
- json对象表示{”name”:”张三”,”age”:”30”} json数组表示[”abc”,100,ture]
数组对象组合嵌套使用[{”name”:”张三”,”age”:”30”},{”name”:”李四”,”age”:”20”},{”name”:”王五”,”age”:”32”}]
- json的解析和序列化(一般情况下,我们的json都是从服务器获取的,获取的json数据是以字符串的形式返回的,这个字符串虽然是json格式的但是不能被直接使用,必须将该字符串转化为一个对象才能正常解析它)
json的解析,即把json数据转换成js对象,JavaScript函数eval()可用于将json文本转换为JavaScript对象,但会执行恶意程序,json解析器只会识别json数据并不会执行
var jsonstr=’ [{”name”:”张三”,”age”:”30”},{”name”:”李四”,”age”:”20”}]’
var jsobj=JSON.parse(jsonstr) alert(jsobj[0].name) //结果:张三
var jsobj2=JSON.parse(jsonstr,function(key,value){if(key==’name’){return ’VIP会员:’+value} else{return value}}) alert(jsobj2[0].name) //结果:VIP会员:张三
json的序列化,即把js对象转换成json数据
var jsobj=[{name:’张三’,age:30},{ name:’李四’,age:28}]
var jsonstr=JSON.stringify(jsobj) alert(jsonstr)
//结果:[{”name”:”张三”,”age”:30},{”name”:”李四”,”age”:28}]
var jsonstr1=JSON.stringify(jsobj,[’age’]) alert(jsonstr1)
//结果:[{”age”:30},{”age”:28}]
var jsonstr2=JSON.stringify(jsobj,function(key,value){if(key==’age’){return ’年龄:’}
else{return value}}) alert(jsonstr2)
//结果:[{”name”:”张三”,”age”:”年龄:30”},{”name”:”李四”,”age”: ”年龄:28”}]
var jsonstr=JSON.stringify(jsobj,null,4) alert(jsonstr) //第三个参数表示缩进
- Ajax
- 什么是Ajax
AJAX=Asynchronous JavaScript and XML(异步的JavaScript和XML)
AJAX可以通过在后台与服务器进行少量数据交换,使网页实现异步更新,这意味着可以在不重新加载整个页面的情况下,对网页的某部分进行更新
<input type=”button” id=”btn” value=”测试按钮”> var btn=document.getElementById(’btn’)
btn.οnclick=function(){var myajax=new XMLHttpRequest() //创建ajax对象
myajax.open(’GET’,’test.txt’,true) //连接服务器
myajax.send(null) //发送请求
myajax.onreadystatechange=function(){if(readyState==4){if(myajax.status==200){alert(’成功’+myajax.responseText)}else{alert(’失败’+myajax.statusText)}}} //接受返回的数据 }
- 正则表达式
- 字符串常用操作
var str=”I am a girl.” alert(str.search(’g’)) //结果:7,若无结果返回-1
alert(str.match(’girl’)) //结果:girl,若无结果返回null
alert(str.replace(’girl’,’boy’)) //结果:I am a boy.
alert(str.split(””,3)) //结果:I,am,a
- 创建正则表达式(i不区分大小写,g全局匹配,m多行匹配)
var str=”aadg44t6tr42w6yuh” var reg=/[a-z]/g alert(str.replace(reg,’’)) //结果:446426
str=’td tdd tddd tdddd’ var reg=/td{1,3}/g alert(str.match(reg)) //结果:td,tdd,tddd
str=’td tdtd tdtdtd’ var reg=/td{1,2}/g alert(str.match(reg)) //结果:td,tdtd
- RegExp对象属性
global,判断regexp对象是否具有标志g;ignoreCase,判断是否具有标志i;multiline,判断是否具有标志m。
source,返回模式匹配所用的文本;lastIndex,返回一个整数,标记开始下一次匹配的字符位置
reg.test(str),判断字符串中是否有指定的值,返回ture或false
reg.compile(/13[0-9]{9}/g),将正则表达式转换为内部的格式,从而执行得更快
reg,exec(str),检索字符串中指定的值,返回一个数组,数组元素0包含了完整的匹配项,元素1-n包含的是匹配项中出现的任意一个子匹配项,若无匹配则返回null
str=”css3 HTML5” var reg=/([a-z]+)\d/g alert(reg.exec(str)) //小括号中为子匹配项,结果:css3,css
exec()方法还返回两个属性,index属性存放匹配文本的第一个字符的位置,input属性存放被检索的字符串
- 表单
- 禁止用户复制和粘贴,onpaste事件在用户向元素中粘贴文本时触发,oncopy事件在用户拷贝元素上的内容时触发
<form action=”#” name=”myform”><input type=”text” name=”text1” value=”禁止复制粘贴”></form>
var text1=document.forms[’myform’].text1
text1.οncοpy=function(){alert(’该内容禁止复制’)} text1.οnpaste=function(){alert(’该内容禁止粘贴’)}
- 回车键切换焦点
<form name=’form1’ action=’#’><input type=’text’ name=’text1’ οnkeydοwn=’swi(form1.text2)’><input type=’text’ name=’text2’ οnkeydοwn=’swi(form1.text3)’><input type=’text’ name=’text3’ οnkeydοwn=’swi(form1.text4)’><input type=’text’ name=’text4’ οnkeydοwn=’swi(form1.text1)’></form>
function swi(str){if(event.keyCode==13) str.focus()}
- 文本内容自动被选中
<form name=’form1’ action=’#’><input type=’text’ name=’text1’ value=’文本内容’ οnclick=’selecttext()’></form>
function selecttext(){if(doucument.form1.text1.focus){document.form1.text1.select()}}
- 遍历下拉列表
<form name=’form1’ action=’’><select name=’sel’ size=’3’ multiple οnchange=’mysel()’><option value=’1’>选项1</option><option value=’2’>选项2</option><option value=’3’>选项3</option><option value=’4’>选项4</option></select><textarea name=’show’ rows=’5’></text></form>
function mysel(){var len=document.form1.sel.option.length var str=’’
for(var i=0;i<len;i++){if(document.form.sel.options[i].selected) str=+document.form1.sel.options[i].text+’\n’}} document.form1.show.value=str
- 级联菜单
<form name=’form1’ action=’’><select name=’sel1’ ><option selected>水果</option><option>蔬菜</option><option>肉类</option></select><select name=’sel2’ ><option>葡萄</option><option>苹果</option><option>西瓜</option></select></form>
var arr=[] arr[’水果’]=[’葡萄’,’苹果’,’西瓜’] arr[’蔬菜’]=[’萝卜’,’茄子’,’番茄’] arr[’肉类’]=[’猪肉’,’牛肉’,’羊肉’]
function changeMenu(){var sel1=document.form1.sel1 var list=arr[sel1.option[sel1.selectedIndex].text]
var menu=document.form1.sel2 remove(menu) for(var i=0;i<list.length;i++){menu[i]=new Option(list[i],list[i])}}
function remove(menu){for(var i=0;i<menu.options.length;i++){menu.options[i]=null}}
- 下拉列表多选移除
<form name=’form1’ action=’’><select size=’6’name=’sel_1’>
<option>1</option><option>2</option><option>3</option><option>4</option></select>
<input type=’button’ value=’<<’ οnclick=’jh(document.form1.sel_2,document.form1.sel_1)’><input type=’button’ value=’>>’ οnclick=’jh(document.form1.sel_1,document.form1.sel_2)’>
<select size=’6’ name=’sel_2’></select></form>
function jh(s1,s2){while(s1.selectedIndex!=-1){var index=s1.selectedIndex var str1=s1.options[index].text s1.remove(index) s2.options.add(new Option(str1))}}
- 单选复选框
设置单选题默认选项 myform.name1.defaultChecked=true
设置多选题最多选择两项
function check(){var num=0 var len=document.myform.name1.length
for(var i=0;i<len;i++){if(document.myform.name1[i].checked) num++}} if(num>2){document.myform.name1[num].checked=false alert(’最多只能选择两项’)}
全选按钮
<input type=’checkbox’ name=’all’ value=’全选’ οnclick=’checkAll(this.checked)’><input type=’checkbox’ name=’check’ value=’A’><input type=’checkbox’ name=’check’ value=’B’><input type=’checkbox’ name=’check’ value=’C’>
function checkAll(c){var arr=document.getElementByName(’check’) if(c){for(var i=0;i<arr.length;i++){arr[i].check=true}} else{ for(var i=0;i<arr.length;i++){arr[i].check=false}}}