这里关于javascript的历史,我就不多说了,想必大家都是知道的,直接进入主题吧。
在网页中使用JavaScript
在网页中使用javascript有两种方式
- 直接在script标签中书协javascript代码
<script type="text/javascript">
window.onload = function() {
alert("write in javascript label");
}
</script>
这里就是直接在script标签中书写的JavaScript代码,window.onload表示当前页面加载完毕执行的代码。
- 引入外部js文件
同样,我们可以将所有当前页面需要用到的JavaScript代码书写到js文件中,然后在该页面中引入即可。
<script type="text/javascript" src="out.js"></script>
javascript函数
在JavaScript中使用函数之前,必须要先定义好函数,才可以调用。函数的定义格式如下:
function 函数名(参数) {
函数体
return
}
<script type="text/javascript">
function writeHello() {
//给页面中输出hello world
document.write("hello world");
}
writeHello();
writeHello();
</script>
这里我定义了一个简单的方法,然后调用两次。
自调用匿名函数
<script type="text/javascript">
(function(param) {
alert("param is :"+param);
alert("hello world");
})(22);
</script>
这里我写了一个匿名函数,并且传入参数调用了自己,这里注意:
function() {} :相当于返回函数的首地址
(function(){}) : 把这部分看成一个整体
(function(){}) () : 根据返回的首地址,调用该函数。
自调用匿名函数的优点:可以避免代码中的函数有重命名问题,并且以上代码只会执行一次,一般用作初始化工作。
javascript变量作用域
<script type="text/javascript">
first = 22; //全局的
var second = 33; //
function sayHello() {
var num = 44; //局部的
numglobal = 55; //全局的
}
</script>
这里可以看出,我们在函数内部定义的变量就是局部的,否则就是全局的,这里的定义是通过var类型来声明的变量。其实在javascript中方法也可以理解是一个类,这里就相当于private和public类型的变量。举个栗子吧:
<script type="text/javascript">
first = 22; //全局的
var second = 33; //
function sayHello() {
var first = 44;//这里的first是局部变量,不影响全局变量
second = 55;//这里的second是全局变量,更改了该值,全局second也跟着更改
}
sayHello();
alert("first is:"+first+"==second is:"+second);
//此时alert的结果first=22,second=55
</script>
小结:在js中,如果某一个变量没有var声明,会自动到上一层的作用域中查找该变量的声明语句,如果找到,就使用,如果没有找到,继续向上查找,一直查找到全局作用域位置,如果全局作用域也没有找到,则系统会自动在全局作用域进行声明该变量。这就是js的作用域链。
JavaScript参数
在javascript中声明的方法是可以带参数的,这里的参数一数组的形式来存放。
<script type="text/javascript">
function hello(first,second) {
for(var i=0; i< arguments.length;i++) {
alert(arguments[i]);
}
}
hello("hello","world");
</script>
这里我声明了一个函数,并且调用了该,传入了声明的参数。首先遍历打印每一个参数值。可以发现,系统会自动将传递的所有参数存放到一个arguments的数组里边,这里,我们可以借助该参数实现不确定参数时候的需求。
JavaScript数组
由于JavaScript是弱类型语言,因此在JavaScript中创建数组的时候,无需指定数组的数据类型,无需指定数组长度,并且可以存储任何类型的数据。
创建数组
在JavaScript中创建数组分为如下三种方式:
<script type="text/javascript">
var arrayOne = [11,"qq",22.5];
var arrayTwo = new Array("second",function(){alert("second array"),11});
var arrayThree = new Array(2);//表示创建一个数组,长度是2
arrayThree[0] = "hello";
arrayThree[1] = "world";
function printArray(array) {
for (var i = 0; i < array.length; i++) {
alert(array[i]);
};
}
printArray(arrayOne);
printArray(arrayTwo);
printArray(arrayThree);
</script>
可以看到,在数组中可以存放任意类型的数据,包括函数,实际上在JavaScript中函数也是对象。
使用for..in语句遍历数组
我们可以使用for循环,和for in语句来遍历数组,这里我只写一个for in的栗子:
function printArray(array) {
for(var i in arrayOne) {
alert(arrayOne[i]);
}
}
javascript多维数组
<script type="text/javascript">
var arrayOne = [[11,"zhangsan"],
[22,"李四"],
[30,"王五"]
];
for (var i = 0; i < arrayOne.length; i++) {
for(var j in arrayOne[i]) {
document.write(arrayOne[i][j]);
}
document.write("<br/>")
};
</script>
JavaScript事件冒泡
先看下面代码:
<html>
<head>
<script type="text/javascript">
window.onload = function() {
var divone = document.getElementById("div1");
var divtwo = document.getElementById("div2");
var divthree = document.getElementById("div3");
divone.onclick = function() {
alert("div1 click");
}
divtwo.onclick = function() {
alert("div2 click");
}
divthree.onclick = function() {
alert("div3 click");
}
}
</script>
</head>
<body>
<div id="div1" style="width:400px;height:400px;background-color='red'">
<div id="div2" style="width:300px;height:300px;background-color='green'">
<div id="div3" style="width:200px;height:200px;background-color='blue'"></div>
</div>
</div>
</body>
</html>
这里我写了三个div,大小不同,从最外层的到最内层的逐渐减小。此时运行效果如下:
可以看到,此时如果点击最内层的div,事件会一次向上传递,那么如何阻止事件继续向最外层传递呢?这里我写了一个方法,该方法兼容ie和w3c,比如在点击了div3之后不希望事件继续向上传递,则只需要在div3的函数运行结束时候,运行该方法即可。
//阻止事件冒泡函数
function stopBubble(e)
{
if (e && e.stopPropagation) {
//W3C
e.stopPropagation()
} else {
//IE
window.event.cancelBubble=true;
}
}
javascript阻止默认事件
<a href="http://www.baidu.com" id="stop">stop default</a>
<script type="text/javascript">
//阻止浏览器的默认行为
function stopDefault(e) {
if (window.event) {
window.event.returnValue = false;
} else {
e.preventDefault();
}
}
window.onload = function() {
var stop = document.getElementById("stop");
stop.onclick = function(e) {
stopDefault(e);
alert("it has stop the default behavior");
}
}
</script>
这里通过stopDefault方法来阻止默认的浏览器事件,兼容ie和w3c标准。
javascript定时器
下面实现一个页面每隔两秒给页面弹出一个hello world
<script type="text/javascript">
function printHello() {
alert("test");
}
setInterval('printHello()',2000);
</script>
这里使用了setInterval(需要调用的方法,间隔时间)。
JavaScript面向对象
类的定义
在JavaScript中类的定义格式如下:
function 类名() {
}
声明对象
var 对象名 = new 类名();
function Person() {
}
var person = new Person();
person.name = "zhansan";
person.age = 22;
person.sex = "man";
alert(person.name+"=="+person.age+"=="+person.sex);
alert(person["name"]+"=="+person["age"]+"=="+person["sex"]);
上面的代码写了一个简单的JavaScript面向对象的栗子,首先声明一个Person类,然后为person对象添加属性,这里需要注意的是,在JavaScript中,我们可以动态的为对象添加任意类型的属性,而不是像java里边,必须先声明好所有的属性。
根据上面的代码可以看出获取对象的属性有两种方式:
- 对象.属性
- 对象[“属性”]
但是还是要注意这两个还是有区别的,如果一个属性原本就含有”.”,那么只能使用 对象[“属性”] 这种方式来获取属性的值
this关键字
在js中有一个this关键字,表示当前调用的该方法的对象,看下面代码:
<script type="text/javascript">
function Person() {
this.name = "zhangsan";
this.age = 20;
}
var p1 = new Person();//此时this表示p1
var p2 = new Person();//此时this表示p2
alert(p1.name+"=="+p1.age);
alert(p2["name"]+"=="+p2["age"]);
</script>
我在声明Person类的时候就为两个属性name和age分别使用this指针附上了对应的值.此时p1和p2对象都拥有name和age属性,并且修改了一个另外一个是保护不变的,此时这两个对象之间是互不干扰的。
向构造函数传递参数
上面的代码,每次new一个新的person对象的时候,这些对象的name和age属性的值都是一样的,我们可以通过给构造方法传递参数来解决该问题。
<script type="text/javascript">
function Person(name,age) {
this.name = name;
this.age = age;
}
var p1 = new Person("zhangsan",22);
var p2 = new Person("lisi",33);
alert(p1.name+"=="+p1.age);
alert(p2["name"]+"=="+p2["age"]);
</script>
此时p1和p2对象默认的name和age属性就不同了。
使用delete删除对象的属性
可以通过js中的delete关键字来删除某一个对象的属性,看下面代码:
<script type="text/javascript">
function Person(name,age) {
this.name = name;
this.age = age;
}
var p1 = new Person("zhangsan",22);
var p2 = new Person("lisi",33);
delete p1.name;//删除p1对象的name属性
alert(p1.name+"=="+p1.age);//打印结果:undefined==22
alert(p2["name"]+"=="+p2["age"]);//打印结果:lisi==33
</script>
javascript静态属性
在java中我们可以使用static关键字来将一个属性描述为类的静态属性,虽然在JavaScript中没有类似的关键字不过我们可以模拟一个静态属性。
语法如下:
类名.属性 = 值 //表示当前类的静态属性
类名.属性 = function() {
}//表示当前类的静态方法
JavaScript闭包
闭包的功能:
- 可以访问局部变量
- 使变量所占的内存不会被释放
先看下面这段代码:
<script type="text/javascript">
window.onload = function() {
function fun1() {
function fun2() {
alert("this is alert by fun2");
}
return fun2;//在fun1方法中,将内部的fun2方法返回
}
var test = fun1();//此时test指向fun2方法的首地址
test();//执行fun2方法,弹出alert("this is alert by fun2");
}
</script>
从上面的代码可以看出,变量可以指向一个函数的首地址,并且一个函数也可以返回另一个函数。
下面我将上面的代码改进一下:
window.onload = function() {
function fun1() {
var num = 22;
function fun2() {
alert("the local num is :"+num);
}
return fun2;//在fun1方法中,将内部的fun2方法返回
}
var test = fun1();//此时test指向fun2方法的首地址
test();//执行fun2方法,弹出alert("the local num is :22");
}
可以看到,这里我在fun1函数中增加了一个局部变量num,发现在fun1函数执行完成之后依然可以访问到该局部变量的值。是因为虽然fun1函数执行完成了,但是fun2函数内部引用了局部变量num,因此num是不会被释放的,正好此时test指fun2函数的首地址,因此执行test就是执行fun2
可以发现只要我们使用一个局部函数引用局部变量,此时局部变量的内存就不会被回收,这样就形成了函数闭包。
JavaScript模拟私有属性
在JavaScript中不想java那样提供了一个特有的private关键字来指明当前属性是一个私有属性,不过我们可以使用JavaScript特有的属性来模拟出一个类的私有属性。
语法如下:
function 类名(arg1,arg2) {//注意这里的arg1,arg2表示形参。
var name = arg1;//此时name是私有属性
this.age = arg2; //此时age是共有属性
}
看下面示例代码:
window.onload = function() {
function Person(name,age) {
this.name = "zhangsan"; //this指向当前调用该方法的对象,因此p1可以访问到name属性
var age = age; //此时由于age使用var声明,所以是局部变量,因此外部不能访问到
}
var p1 = new Person("zhangsan",22);
alert(p1.name+"=="+p1.age);//打印结果:zhangsan==undefined
}
这里虽然通过var声明的属性我们不能再外部访问了,可是如果该变量我们无法获取和设置其值,又有什么用呢??下面我们来添加一个类似于java当中的get和set方法来解决这个问题。看下面代码:
function Person(name,age) {
this.name = "zhangsan"; //this指向当前调用该方法的对象,因此p1可以访问到name属性
var age = age; //此时由于age使用var声明,所以是局部变量,因此外部不能访问到
//通过this为当前调用该方法的对象设置一个getAge方法,用来获得局部变量age的值
this.getAge = function(){
return age;
};
//通过this为当前调用该方法的对象设置一个setAge方法,用来设置局部变量age的值
this.setAge = function(a) {
age = a;
};
}
var p1 = new Person("zhangsan",22);
//通过getAge方法获得局部变量age的值
alert(p1.name+"=="+p1.getAge());//打印结果:zhangsan==22
p1.setAge(11); //重新为age设置值
alert(p1.getAge()); //打印结果:11
JavaScript中apply和call方法的使用
我们都知道在JavaScript的方法中,如果那个对象调用了该方法,那么内部的this就表示那个对象,我们可以使用apply和call任意方法来指定当前调用的对象。
语法如下:
call(那个对象调用,arg1,arg2,arg3,....argN);
apply(那个对象调用,[arg1,arg2,arg3,....argN]);
先看如下代码:
window.onload = function() {
function Person(name,age) {
this.name = "zhangsan";
var age = age;
}
function sayHello() {
alert(this.constructor); //通过打印的constructor判断当前this表示那类对象
alert("hello world");
}
var p1 = new Person("zhangsan",22);
//p1.sayHello(); 此时不能使用p1调用sayHello方法,因为p1没有改方法。
}
此时由于sayHello方法不属于p1因此p1也就无法调用该方法。
不过我们可以通过如下方式调用sayHello方法:
sayHello.call(p1);
sayHello.apply(p1);
此时打印出的构造方法如下:
注意这里当不带参数的时候,apply和call的用法是相同的。
下面为sayHello方法加上两个参数:
function Person(name,age) {
this.name = "zhangsan";
var age = age;
}
function sayHello(hello,world) {
alert(this.constructor); //通过打印的constructor判断当前this表示那类对象
alert(hello+"---"+world);
}
var p1 = new Person("zhangsan",22);
//p1.sayHello(); 此时不能使用p1调用sayHello方法,因为p1没有改方法。
sayHello.call(p1,"hello","world");
sayHello.apply(p1,["hello","world"]);
可以看到,call和apply方法的意义是相同的,不同的是当被调用的参数需要传递参数的时候,参数的传递不同而已。
JavaScript继承
在java中,我们可以通过extends关键字来实现继承到指定的类,在JavaScript中并没有给我们提供相应的实现,不过我们可以通过特定的语法来实现JavaScript的继承。
语法如下:
子类.prototype = new 父类();
下面我实现一个简单的student类继承自person类的栗子:
function Person(name,age) {
this.name = name;
this.age = age;
this.sayHello = function() {
alert(this.name+"==="+this.age);
}
}
function Student(id,name,age) {
this.id = id;
this.read = function() {
alert(this.id+"=="+this.name+"==="+this.age);
}
}
Student.prototype = new Person("zhangsan",11);//表示Student类继承自Person类
var student = new Student(1001);
student.read();
student.sayHello();//此时的sayHello是调用从父类中继承的方法
此时运行效果如下:
可以看到student类中并没有sayHello方法,而调用的正是从父类继承过来的。
ok,今天关于JavaScript的学习就到这里了。