(2):通过DOM对象的onxxx属性来设置。
此时onxxx属性的值只能是一个函数的引用。
在第一种方法中:因为事件(onclick)在网页上,所以在出现问题的
时候,程序员和美工人员会扯皮。解决方法是把javascript代码分离出来,
把页面上所有的元素设置id。
注意:在上图中的"document.getElementById("mybut").onclick=test"中是
“test”而不是test(),因为通过DOM对象的onxxx属性的值只能是一个函数的引用。
如果是test()则onclick接收的是test()函数的返回值。可以是如下图的代码:
上图中,页面一打开就会弹出警告,说明test()执行了函数体。
但是上边的情况都是javascript代码在</body>以前,但是如果把它放到<head>里如下:
<html>
<head>
<script type="text/javascript" src="test.js">
</script>
</head>
<body>
<div id="target">
</div>
<button id='mybut'">添加内容</button>
</body>
</html>
则会弹出以下的错误:找不到mybut,因为javascript是顺序执行的。
解决方法如下:
下面alert以下test函数的内容:
***********************************************************
5、
第二: 定义函数的时候同时就产生了一个JS类。
function Person(name,age)
{
/*
把函数当做类使用时,函数里的变量可分为
(1)类变量:以函数名作为前缀的变量就是类变量
(2)实例变量:以this作为前缀的变量就是实例变量
(3)局部变量:没有修饰符的变量就是局部变量,或者使用var修饰。
(4)函数可当做类的方法。
*/
this.name=name;
this.age=age;
//Person类的类变量
Person.eyeNum=2;
//函数永远是独立存在的,即使把它定义在一个类中。
this.info=function()
{
alert(this.name+"--->"+this.age);
};
}
var p=new Person("刘晓华",555);
p.info();
//function定义的既是一个函数,也是一个类,同时也是这个类的构造器
function Dog(name,age)
{
this.name=name;
this.age=age;
}
var d=new Dog("狗狗",5);
/*
call是一个特殊的用法;
xxx是一个函数,调用xxx函数有三个写法:
调用者.xxx(p1,p2,p3)=xxx.call(调用者,p1,p2,p3)
*/
p.info.call(d);
6、
用var和不用var的区别:
(1)不用var:
如果上下文中该变量存在,直接用已有的变量;
如果上下文中该变量不存在,才声明一个新的变量
(2)用var,表示声明一个新的变量。
7、
call的用法:
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
var a=20;
b="bbbb";
function test()
{
alert("a:"+a+",b:"+b);
}
//test();默认的调用者是window
window.test();
age=23;
alert(window.age);
//alert(age);
test.call(window);
//test.call();
var o=new Object();
test.call(o);
var f=new Function();
test.call(f);
</script>
</html>
8、
调用函数的方式:
第一种:
调用者.函数名(参数列表);
调用者可以省略
第二种:
函数名.call(调用者,参数列表);
第三种:
函数名.apply(调用者,arguments);
9、
this前缀的作用:
当在函数里访问一个变量时,
如果使用了this前缀,
程序只搜索主调对象里是否包含该实例变量,
如果不存在,当成undefined处理。
<script type="text/javascript">
var a=20;
function test()
{
alert(this.a);
}
var o=new Object();
//undefined
test.call(o);
//20
test.call(window);
</script>
如果没有this前缀:
a、程序会先搜索当前函数中是否存在该局部变量
b、如果a搜索不存在,程序会搜索主调对象中是否存在该实例变量;
c、如果b搜索还不存在,程序会先搜索主调对象所在的对象中是否存在该局部变量
一直向上,直到window对象为止。
<script type="text/javascript">
var a=20;
function test()
{
alert(a);
}
var o=new Object();
//20
test.call(o);
//20
test.call(window);
</script>
10、
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
var v=function(a,b)
{
this.test=a+b;
}
v(2,3);
//因为主调对象是window,所以是5
alert(window.test);
var o=new Object();
v.call(o,22,11);
//因为主调对象是o,所以是33
alert(o.test);
//以下还是以前window调用的,所以是5
alert(test);
alert(window.test);
</script>
</html>
11、
<html>
<head>
</head>
<body>
<script type="text/javascript">
var f=function(x,y){}
f(2,3);
//function(x,y){}(2,3);和上边的是定义是等价的
</script>
</body>
</html>
12、
apply方法: 函数名.apply(调用者,arguments);
apply和call的本质是一样的,只不过apply可以通过
arguments来访问当前函数的参数。
<html>
<head>
</head>
<body>
<script type="text/javascript">
function test(a,b)
{
alert(a+b);
}
var f=function(x,y)
{
var o=new Object();
test.apply(o,arguments);//arguments表示从f函数中接收参数
}
alert("...........");
//5
f(2,3);
</script>
</body>
</html>
13、
注意以下2种代码的不同:
(1)
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
function Person(name,age)
{
this.name=name;
this.age=age;
Person.info=234;
}
alert(Person.info);//在Person没执行之前,Person.info=234;也没执行
var p=new Person("name",1);
</script>
</html>
运行如下:
(2)
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
function Person(name,age)
{
this.name=name;
this.age=age;
Person.info=234;
}
var p=new Person("name",1);
alert(Person.info);
</script>
</html>
14、
(1)在java中:
public class A{
int a=33;
public void a(){
System.out.println(a);
int a=3;
System.out.println(a);
}
public static void main(String[]a){
A b=new A();
b.a();
}
}
打印的结果为:
33
3
(2)但是在javascript中:
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
var a="a";
var b=function (){
document.writeln(a);
var a="aa";
document.writeln(a);
}
b();
</script>
</html>
输出的结果为:
undefined aa
解析:因为函数b有声明的新变量a,所以会屏蔽函数外的a,而javascript是顺序执行的,
所以第一个“document.writeln(a);”会输出“undefined ”。这和java的情况完全
不一样。谨记!
15、
(1)
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
var a=2;
var a=33;
alert(a);
</script>
</html>
输出的结果为:33
说明后边的新声明的变量a会把前边的a覆盖掉。
同样也适用于函数,如下:
(2)
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
function test(){
alert("!!");
}
function test(a,b,c)
{
alert("a:"+a+"\nb:"+b+"\nc:"+c);
}
test();
test(2);
test(2,3);
test(2,3,4);
</script>
</html>
结果如下:
解析:js函数不存在所谓的重载,如果两个函数同名,后边的会把前面的覆盖。
并且允许实参个数和形参个数可以不匹配,没有传入实参的值当成undefined。
和下边的是一样的:
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
var test =function(){
alert("!!");
}
var test =function(a,b,c)
{
alert("a:"+a+"\nb:"+b+"\nc:"+c);
}
test();
test(2);
test(2,3);
test(2,3,4);
</script>
</html>
16、
“==”和“===”的区别:
“==”:普通相等,会把两个参与比较的表达式,转换为相同类型之后进行比较。
“===”:精确相等。
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
alert("223"==223);
alert("223"===223);
alert(undefined==null);//undefined表示完全不存在。
alert(undefined===null);
</script>
</html>
结果为:true,false,true,false
17、
“!=”:普通不相等,会把两个参与比较的表达式,转换为相同类型之后进行比较。
比较时不再理会数据类型。
“!==”:精确不相等。只要数据类型不相同,或者值不同都会返回true。
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
alert("223"!=223);
alert("223"!==223);
</script>
</html>
结果为:false,true
18、
JS的类和对象
JS如何定义类?
js在定义函数的时候,同时也定义了类,并为该类提供了构造器。
JS类的继承:
通过prototype继承。
js中功能上的子类与功能上的父类的具有相同的类名;
可以为系统的类增加方法。
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
function Person(name,age)
{
this.name=name;
this.age=age;
/*每次实例化一个对象在内存中就会开辟新的name,age,info空间,创建一个新的函数
所以可能会有“内存泄露”
this.info=function()
{
alert(this.name+this.age);
}
*/
}
//如果要为Person类定义方法,可用prototype来动态的添加
Person.prototype.info=function(){
alert(this.name+this.age);
}
var x=new Person("s",3);
var y=new Person("y",3);
x.info();
y.info();
Person.prototype.run=function()//不是Person的独有函数
{
alert(this.name+this.age);
}
x.run();
y.run();
x.run.call(window);
</script>
</html>
19、
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
var a=[1,2,3,"a",'b'];//a为数组
alert(a);
alert(a.length);//为5
</script>
</html>
20、
为系统的类增加方法。
<html>
<head>
<script type="text/javascript">
Array.prototype.each=function()//为系统类Array增加一个each方法
{
for(var i=0,len=this.length;i<len;i++)//this表示调用此函数的数组
{
alert(this[i]);//数组的第i个值
}
}
Array.prototype.map=function(fn)//为系统类Array增加一个map方法
{
var result=new Array(this.length);
for(var i=0,len=this.length;i<len;i++)
{
//因为fn函数的返回值跟调用者没一点关系,所以下边的一句可以是:
//result[i]=fn.call(null,i,this[i]);
//result[i]=fn.call(window,i,this[i]);
result[i]=fn.call(this,i,this[i]);
}
return result;
}
</script>
</head>
<body>
</body>
<script type="text/javascript">
var a=[1,2,3];
a.each();
var newArr=a.map(function(index,ele)
{
return ele*ele;
}
);
alert(newArr);
alert(a.map(function(index,ele)
{
return ele+ele;
}
));
alert(a.map(function(index,ele)
{
return Math.sqrt(ele);
}
));
</script>
</html>
21、
对于trim()的使用,有的浏览器支持(比如:360),有的浏览器会报错(比如IE)。
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
alert("a"+" b ".trim()+"c");
</script>
</html>
但是可以修改一下:
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
String.prototype.trim=function()
{
/*在javascript中的正则表达式中,“/……/”表示正则表达式
“^”:代表开始
“s”:代码空,space
“S”:不是空白
“n”:数字,number
“N”:不是数字
“w”:单词字符,word
“W”:不是单词字符
“.”:任意字符
“+”:一个或一个以上
“$”:结束
*/
return this.replace(/^\s+/,"").replace(/\s+$/,"");
}
alert("a"+" b ".trim()+"c");
</script>
</html>
22、
关于20号知识点中的“each”函数,可以修改如下:
<html>
<head>
<script type="text/javascript">
Array.prototype.each=function(fn)
{
for(var i=0,len=this.length;i<len;i++)
{
fn.call(null,this[i]);
}
}
</script>
</head>
<body>
</body>
<script type="text/javascript">
var a=[1,2,3];
a.each(function(ele){alert(ele);});
</script>
</html>
23、
创建对象的方式:
(1)通过new调用构造器。并不太好。
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
function Person()
{
}
var p=new Person();
/*
JS没有严格的类继承关系,
JS的类层次只有2层:所有类都继承了Object类
*/
//true
alert(p instanceof(Person));
//true
alert(p instanceof(Object));
</script>
</html>
(2)通过new Object()来创建,
其实也是调用构造器,只是调用Object的构造器来创建对象。
也不太好。
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
var o=new Object();
alert(o instanceof(Object));
alert(o.toString());
</script>
</html>
众所周知,java是静态语言,即:空间开辟好以后就不能移动,看下边的例子:
class A{
int a=3;
public static void main(String[]a)
{
A a=new A();//a里存的是地址。
a=new A();//又开辟一个新的空间,空间的地址的值赋给了a,那么上句开辟的空间就成了垃圾空间
}
}
而Js是动态语言,对象的属性、方法可以动态的改变。
直接为对象的不存在的属性赋值,就相当于为该对象增加一个属性;
直接为对象的不存在的属性赋值并赋值为方法,就相当于给该对象增加了个方法。
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
var o=new Object();
//只有你愿意,属性和方法随意添加。动态嘛
name="是否";
age=23;
o.name="小泽玛利亚";
o.age=123;
o.info=function()
{
alert(this.name+this.age);
}
//info()不是仅仅属于o的,而是独立存在的,记住:函数永远是独立存在的!!!!
//"小泽玛利亚"123
o.info();
//是否23
o.info.call(window);//方法名(或者说是引用).call(调用者,参数列表)
//上句不能使用info.call(window),因为只有到o里才能搜索到info
</script>
</html>
(3)使用JSON语法
JSON:javascript object notation
现在已经成为一种跨平台、跨语言的通用的数据交换格式。
也是一种轻量级的序列化机制。
关于JSON:记住两个符号
{}代表对象。
[]代表数组。
()不存在!
上边的多维数组在java里也可以表示:
class A{
public static void main(String[]a)
{
Object[] arr=new Object[12];//一维
arr[0]=new Object[5];//变为二维
arr[0][0]=new Object[4];//变为三维
arr[0][0][0]=new Object[5];//变为四维
……………………………………
随意多个维的都可以。
}
}
JSON的用法:
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
obj=[];
//0
alert(obj.length);
obj[100]="张三";
//张三
alert(obj[100]);
//101
alert(obj.length);
obj[23]=["23"];//把一维数组赋给obj
//23
alert(obj[23]);
obj[3]=[[[[[8]],33]]];
alert(obj[3]);
alert(obj[3][0][0][0][0][0]);
obj[5]={/对象
age:0,
sex:"男",
go:function()
{
alert("go");
}
eat:[//eat属性是个数组
function(){},function(){},function(){}
],
par:[
{
name:"par的名字",
age:33
},
{
name:"par的2名字",
age:222
}
],
son:{
schools:["小学","总学"]
}
};
//动态增加属性和方法
obj[5].name="第六位的名字";
obj[5].info=function()
{
alert("obj[5]的动态方法");
}
</script>
</html>
只要是动态语言就不需要list集合,因为数组就满足了。
JS的对象完全可代替Map集合。
24、
这些覆写Object类的toString方法对吗?
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
Object.prototype.toString=function()
{
alert("s");
}
var o=new Object();
//s
o.toString();
</script>
</html>
25、
eval的用法:
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
var str="var d=33;alert(d)";
eval(str);
</script>
</html>
26
实现级联菜单的联动:
<html>
<head>
</head>
<body>
<select id="province" style="width:150px">
</select>
<select id="cities" style="width:150px">
</select>
</body>
<script type="text/javascript" src="cascade.js">
</script>
</html>
其中cascade.js代码如下:
var data=[
{id:1,
name:"湖南",
cities:[{id:11,name:"长沙"},{id:12,name:"衡阳"},{id:13,name:"岳阳"},{id:14,name:"益阳"}]
},
{id:2,
name:"湖北",
cities:[{id:21,name:"武汉"},{id:22,name:"荆州"},{id:23,name:"黄冈"},{id:24,name:"鄂州"}]
},
{id:3,
name:"河南",
cities:[{id:31,name:"郑州"},{id:32,name:"南阳"},{id:33,name:"开封"},{id:34,name:"商丘"}]
}
];
var province=document.getElementById("province");
var cities=document.getElementById("cities");
//清空province里的内容
province.innerHTML="";
for(var i=0,len=data.length;i<len;i++)
{
var op=document.createElement("option");
op.value=data[i].id;
op.innerHTML=data[i].name;
province.appendChild(op);
}
/*
下边的代码也可以这样:
var onch=function(){.....}
province.onchange=onch;
*/
province.onchange=function()
{
cities.innerHTML="";
//得到选中省份的ID
var proId=province.value;
for(var i=0,len=data.length;i<len;i++)
{
if(data[i].id==proId)
{
var cityData=data[i].cities;
for(var i=0,len= cityData.length;i<len;i++)
{
var op=document.createElement("option");
op.value= cityData[i].id;
op.innerHTML= cityData[i].name;
cities.appendChild(op);
}
break;
}
}
};
27、html文档《--》DOM树
DOM:document object model文档对象模型;
DOM: document object mapping文档对象映射。
通过DOM转换,就可以吧HTML文档的所有节点当成“内存中对象”来处理。
如果直接修改HTML文档,只能以IO流的形式来修改;转换为DOM对象后,
就可以通过调用方法、访问属性来修改DOM对象。
一切都是NOde(节点)
除了文档之外,其他HTML标签都是元素(Element),所有的HTML标签都是HTMLElement。
除了继承关系之外,DOM对象之间,还存在严格的包含关系。
对HTML文档进行修改:
查:得到HTML节点对应的DOM对象。
第一种方式:
document.getElementById();
第二种方式:
利用节点之间的父子、兄弟关系来来获取。
<html>
<head>
</head>
<body>
<div>
<div>第一个节点</div>
<div id="son">子节点</div>
<p>页面内容</p>
</div>
<button onclick="change();">试试</button>
<script type="text/javascript">
var change=function(){
//如果document存在
if(document){alert("document存在");}
//如果getElementById方法存在
//为什么可以这样判断呢?因为:
//getElementById=function(){},从某种意义上说,getElementById也算是属性了
//
if(document.getElementById)alert("方法存在");
var son=document.getElementById("son");
son.parentNode.style.width="400px";
son.parentNode.style.width="400px";
son.parentNode.style.backgroundColor="#aaa";
var prev=son.previousSibling;
//找到son节点上的一个非文本的兄弟节点
while(!prev.innerHTML)
{
prev=prev.previousSibling;
}
prev. style.border="2px dotted black";
}
</script>
</body>
</html>
第三种方式:对于表单,也就是HTMLFormElement,它有以下两个属性:
HTMLCollection elements:返回该表单内所有的表单控件。
long length:返回该表单内表单控件的个数。
<html>
<head>
<script type="text/javascript" src="validate.js">
</script>
</head>
<body>
<form id="a" method="post" action="">
用户名<input type="text" name="name"/>
密码:<input type="text" name="pass"/>
年龄:<input type="text" name="age"/>
<input type="button" value="检查" onclick="checkForm();"/>
</form>
<script type="text/javascript">
var checkForm=function()
{
check("a",{
"name":"required",
"pass":{type:"regex",expr:/\w{4,8}/},
"age":"int"
});
};
</script>
</body>
</html>
其中validate.js代码如下:
String.prototype.trim=function()
{
return this.replace(/^\s+/,"").replace(/\s+$/,"");
}
var errMsg={
"required":"必须填写",
"int":"必须是一个整数",
"regex":"必须符合要求的格式"
}
var check=function(formid,fields)
{
var targetForm=document.getElementById(formid);
for(var fieldName in fields)//fieldName依次代表fields对象里的每个key
{
var errResult="";
var fieldVal=targetForm.elements[fieldName].value;
var rule=fields[fieldName];
if(typeof(rule)=="string")
{
switch(rule)
{
case "requirred":
if(!fieldVal||fieldVal==null||fieldVal.trim) {errResult+=fieldName+errMag["required"];}
break;
case "int":
if(fieldVal&&fieldVal!=nullfieldVal.trim!="") {
try{
if(isNaN(parseInt(fieldVal)))
{
errResult+=fieldName+(errMag["int"]+"\n");
}
}catch(e){errResult+=fieldName+(errMag["int"]+"\n");}
}
else
{
errResult+=fieldName+errMag["required"];
}break;
}
}
else
{
switch(rule.type)
{
}
}
if(errResult!="")
{
alert(errResult);
return false;
}
return true;
}
}
增:
增加节点之前,先创建节点,有如下几种方式:
第一种:document.createElement 完全新建一个节点,有时候性能较差。
第二种:克隆一个节点,cloneNode(boolean deep),也会把包含的子节点也克隆出来。
<html>
<head>
</head>
<body>
<table id="target" style="width:400px" border="1">
<tr>
<th>名字</th>
<th>颜色</th>
</tr>
<tr>
<td>小红</td>
<td>白色</td>
</tr>
</table>
名字:<input type="text" id="name"/><br/>
颜色:<input type="text" id="color"/><br>
<button onclick="addRow();">添加</button>
<script type="text/javascript">
var targetTb=document.getElementById("target");
var addRow=function()
{
var newRow=targetTb.rows[1].cloneNode(true);
newRow.cells[0].innerHTML=document.getElementById("name").value;
newRow.cells[1].innerHTML=document.getElementById("color").value;
targetTb.appendChild(newRow);
}
</script>
</body>
</html>
注意:以上代码在IE浏览器上运行不了,但是在360浏览器上可以运行。
第三种:
new Option(text,value);
前两种是对所有节点都可用,后一种对某些节点可用。
添加节点的方法:
第一种:
通用方式,appendChild--永远在父节点的最后添加。
insertBefore(Node newChild,Node refChild);把节点添加到指定位置。
replaceChild(Node newChild, Node oldChild);把oldChild替换成newChild.
第二种:
对于select元素,如下:
add(option,before)在指定的option前面添加一个新的option;如果before为null,那就添加到最后。
<html>
<head>
</head>
<body>
<input type="text" id="a"/><br/>
<input type="text" id="b"/><br>
<select id="target" style="width:120px">
</select>
<button onclick="addOp('target',$('a').value,$('b').value,
$('target').options[$('target').selectedIndex]
);">添加</button>
<script type="text/javascript">
var $=function(id)
{
return document.getElementById(id);
}
var addOp=function(targetSelect,text,val,before)
{
var target= $(targetSelect);
var op=new Option(text,val);
target.add(op,before);
}
</script>
</body>
</html>
第三种:
对于表格:
insertRow 增加一行
insertCell增加一个单元格。