当前位置: 代码迷 >> JavaScript >> javascript学习札记(未完待续)
  详细解决方案

javascript学习札记(未完待续)

热度:421   发布时间:2013-04-12 18:33:11.0
javascript学习笔记(未完待续)
1、因为javascript是弱类型的语言,所以不用定义类型。
2、定义函数的方法:
  第一种:
   function add(x,y){return x+y;}
   第二种:定义匿名函数(主流的方法)
   function(x,y){return x+y;}


例:
 
 <html>
<head></head>
<body>
<script type="text/javascript">
var myfun=function(x,y){return x+y;}
//只要一个变量引用的是对象,他就是Object的实例
alert(myfun instanceof Object);
//只要一个变量引用的是函数对象,他就是Function的实例
alert(myfun instanceof Function);
alert(myfun(3,4));
</script>
</body>
</html>




  第三种:
  可以调用Function的构造器来创建函数
  new Function(p1,p2,....,pN);
前面的pN-1个形参将会作为新创建函数的形参列表,而pN就是函数体。
例如:


 var fun=new Function("x","y","z","x=y+z;return x+y+c");
alert(fun(2,3,4));
3、
  在java里,类是一等公民,类是可以独立存在的程序单元。
  在javascript中,函数式一等公民,函数式可以独立存在的程序单元。


4、
  函数的功能:
 第一:为普通的函数(把函数当函数用)。
例如:
<html>
<head>
<script type="text/javascript">
  var test=function()
{


var ele=document.createElement("span");
    ele.innerHTML="添加的内容";
   document.getElementById("target").appendChild(ele);
}
</script>
</head>


<body>
<div id="target">
</div>
<button onclick="test();">添加内容</button>
<input type="button" value="添加内容" onclick="test();"/>
</body>
</html>
注意:<button onclick="test();">中的test()后最好跟一个分号,
      因为这是条语句。
***********************************************************
最主要的绑定事件监听的方法:
    (1):通过HTML标签的onxxx属性来设置。此时onxxx属性的值可以
是一条或n条js语句。
例如:
   <html>
<head>


</head>


<body>
<div id="target">
</div>
<button onclick="var target=document.getElementById('target');target.innerHTML='test'";>添加内容</button>


</body>
</html>

(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增加一个单元格。
 

  相关解决方案