JavaScript基础知识点归纳

定义在函数外的变量一定是全局变量;定义在函数内的变量,如果声明了var,那该变量就是局部变量,如果不声明var,那么该变量就是全局变量。

JavaScript
?
1
2
3
4
5
6
7
8
9
var global = "Global" ;
test();
function test(){
   var local = "Local" ;
   document.writeln(global);
   document.writeln(local);
}
document.writeln(global);
document.writeln(local);

2、两种类型的Cookie

i)持久性cookie,会被存储到客户端的硬盘上。

ii)回话cookie:不会被存储到客户端的硬盘上,而是放在浏览器进程所处的内存当中,当浏览器关闭时则该回话cookie就销毁了。

3、在JavaScript中,函数(function)就是对象

4、在JavaScript中,没有方法(函数)重载的概念

5、Function对象

在JavaScript中有一个Function对象,所有自定义的函数都是Function对象类型的。Function对象接受的所有参数都是字符串类型的,其中最后一个参数就是要执行的函数体,而前面的参数则是函数真正需要接受的参数。

6、隐含的对象arguments

在JavaScript中,每个函数都有一个隐含的对象arguments,表示给函数实际传递的参数。arguments.length就表示实际传递的参数的个数。

7、函数名.length

每一个函数对象都有一个length属性,表示该函数期望接受的参数个数。它与函数的arguments不同。arguments.length表示函数实际接受的参数个数。

8、JavaScript中有五种原始数据类型

Undefined、Null、Boolean、Number以及String。(注意:在JavaScript中,没有char数据类型)

Undefined数据类型的值只有一个:undefined;

Null数据类型的值只有一个:null;

Boolean数据类型的值有两个:true和false;

9、typeof运算符

typeof是一元运算符,后跟变量的名称,用于获取变量的数据类型,其返回值有5个:undefined、boolean、number、string以及object。

10、在JavaScript中,如果函数没有声明返回值,那么会返回undefined11、null与undefined的关系

undefined实际上是从null派生出来的。例如:

null与undefined的关系

JavaScript

?
1
2
alert(undefined == null );
//浏览器返回true

11、强制类型转换

在JavaScript中有3种强制类型转换:Boolean(value),Number(value),String(value)。

12、Object对象

在JavaScript中,所有对象都是从Object对象继承过来的。

Object对象

JavaScript

?
1
2
3
4
var object = new Object();
for ( var v in object){
   alert(v);
}

上面的代码中,浏览器并没有打印出什么,并不能说明Object对象不带有任何属性。下面代码测试Object对象中的属性是否可以枚举,如果返回false,则说明Object对象中的属性是不能枚举的。

Object对象中的属性是不能枚举的

JavaScript

?
1
alert(object.propertyIsEnumerable( "prototype" ));

浏览器弹出false对话框,则说明Object对象中的属性是不能枚举的。

接下来我们再看看window对象中的属性是否可以枚举的

window对象中的属性是可以枚举的

JavaScript

?
1
2
3
for ( var v in window) {
   console.log(v);
}

在Chrome浏览器中我们会看到浏览器调试控制台中打印出一大堆属性,说明window对象中的属性是可以枚举的。

13、在JavaScript中,可以动态添加对象的属性,也可以动态删除对象的属性

动态添加/删除对象的属性

JavaScript

?
1
2
3
4
5
6
7
8
9
10
11
var object = new Object();
alert(object.username); //undefined
  
object.username = "zhangsan" ;
alert(object.username); //zhangsan
  
object[ "password" ] = "123" ;
alert(object.password); //123
  
delete object.username; //此时,username属性已经被删除
alert(object.username);

14、JavaScript中定义对象最常见的方式

定义对象最常见的方式

JavaScript

?
1
2
3
4
5
6
var object = {
   username: "zhangsan" ,
   password:12345
};
alert(object.username);
alert(object.password);

15、数组

数组定义

JavaScript

?
1
2
3
4
5
6
7
8
9
10
11
//方法一
var array = new Array();
array.push(1);
array.push(2);
array.push(3);
alert(array.length);
  
//方法二(推荐)
var array = [1,25,4];
array.sort();
alert(array);

调用数组的sort()方法,浏览器打印1,25,4,这并不是我们期望的结果。

对于JavaScript数组的sort方法来说,它会先将待排序的内容转换为字符串(调用toString()方法),按照字符串的先后顺序进行排序。

下列方式可以得到我们期望的结果(按数组大小进行排序):

数组排序

JavaScript

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function compare(num1,num2) {
   var temp1 = parseInt(num1);
   var temp2 = parseInt(num2);
   if (temp1 < temp2) {
     return -1;
   } else if (temp1 == temp2) {
     return 0;
   } else {
     return 1;
   }
}
  
var array = [1,25,3];
array.sort(compare);
alert(array);

我们再用匿名函数的方式实现:

匿名函数排序

JavaScript

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var array = [1,25,3];
  
array.sort( function (num1,num2){
   var temp1 = parseInt(num1);
   var temp2 = parseInt(num2);
   if (temp1 < temp2) {
     return -1;
   } else if (temp1 == temp2) {
     return 0;
   } else {
     return 1;
   }
});
  
alert(array);

16、JavaScript中定义对象的5种方式(JavaScript中没有类的概念,只有对象)i)基于已有对象扩充其属性和方法

基于已有对象扩充其属性和方法

JavaScript

?
1
2
3
4
5
6
7
8
9
var object = new Object();
//添加name属性
object.name = "zhangsan" ;
//添加sayName方法
object.sayName = function (name) {
   this .name = name;
   alert( this .name);
};
object.sayName( "kyle" ); //调用sayName方法,name属性被修改为kyle,浏览器将打印kyle

最简单的一种方式,使用起来并不方便,适合于临时需要一个对象。

ii)工厂方式创建对象

不带参数的工厂方法:

JavaScript

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//工厂方法
function createObject() {
   var object = new Object(); //创建一个对象
   object.name = "zhangsan" ; //为该对象添加一个name属性
   object.password = "123" ; //为该对象添加一个password属性
   object.get = function () { //为该对象添加一个get方法
     alert( this .name+ "," + this .password);
   };
   return object; //返回该对象
}
  
var object1 = createObject(); //调用createObject工厂方法创建对象object1
var object2 = createObject(); //调用createObject工厂方法创建对象object2
object1.get(); //调用对象get方法
object2.get(); //调用对象get方法

带参数的工厂方法:

JavaScript

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function createObject(name,password) {
   var object = new Object();
   object.name = name;
   object.password = password;
   object.get = function () {
     alert( this .name+ "," + this .password);
   };
   return object;
}
  
var object1 = createObject( "zhangsan" , "123" );
var object2 = createObject( "lisi" , "456" );
object1.get();
object2.get();

上面两种不带参数和带参数的工厂方法缺点:

每创建一个对象,内存中就创建一个get方法,比较浪费内存,且影响性能。而我们的期望是,创建两个不同的对象,它们的属性是不一样的,但方法是共用的。所以接下来我们需要改进createObject工厂方法。

改进的工厂方法:

JavaScript

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function get(){
   alert( this .name+ "," + this .password);
}
  
function createObject(name,password) {
   var object = new Object();
   object.name = name;
   object.password = password;
   object.get = get;
   return object;
}
  
var object1 = createObject( "zhangsan" , "123" );
var object2 = createObject( "lisi" , "456" );
object1.get();
object2.get();

 将get方法定义在createObject函数外面,这样每创建一个对象,get方法都是共用的。让一个函数对象被多个对象所共享,而不是每一个对象都拥有一个函数对象。

iii)构造函数方式创建对象

不带参数的构造函数:

JavaScript

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
function Person(){
   //在执行第一行代码前,js引擎会为我们生成一个对象
   this .name = "zhangsan" ;
   this .password = "123" ;
   this .getInfo = function () {
     alert( this .name+ "," + this .password);
   };
  
   //此处有一个隐含的return语句,用于将之前生成的对象返回(也是跟工厂方式不一样的地方)
}
  
var p1 = new Person();
p1.getInfo();

带参数的构造函数

JavaScript

?
1
2
3
4
5
6
7
8
9
10
11
12
function Person(name,password) {
   this .name = name;
   this .password = password;
   this .getInfo = function () {
     alert( this .name+ "," + this .password);
   };
}
  
var p1 = new Person( "zhangsan" , "123" );
var p2 = new Person( "lisi" , "456" );
p1.getInfo();
p2.getInfo();

iv)原型(prototype)方式创建对象

prototype是Object对象里面的一个属性

prototype

JavaScript

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Person(){
  
}
Person.prototype.name = "zhangsan" ;
Person.prototype.password = "123" ;
Person.prototype.getInfo = function () {
   alert( this .name+ "," + this .password);
};
  
var p1 = new Person();
var p2 = new Person();
p1.name = "kyle" ; //对象生成之后再去改变属性
p1.getInfo();
p2.getInfo();

单纯地使用原型方式有两个问题:第一,你无法在构造函数中为属性赋初值,只能在对象生成之后再去改变属性值。

prototype

JavaScript

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Person(){
  
}
Person.prototype.name = new Array();
Person.prototype.password = "123" ;
Person.prototype.getInfo = function () {
   alert( this .name+ "," + this .password);
};
  
var p1 = new Person();
var p2 = new Person();
p1.name.push( "zhangsan" );
p1.name.push( "lisi" );
p1.password = "456" ;
p1.getInfo();
p2.getInfo()

浏览器将会打印:zhangsan,lisi,456 和 zhangsan,lisi,123.

如果使用原型方式创建对象,那么生成的所有对象会共享原型中的属性,这样一个对象改变了该属性也会反应到其他对象当中。所以单纯地使用原型方式是不行的,还需要结合其他方式。接下来我们会继续介绍。

使用原型+构造函数方式来定义对象

JavaScript

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Person() {
   this .name = new Array();
   this .password = "123" ;
}
Person.prototype.getInfo = function () {
   alert( this .name+ "," + this .password);
};
  
var p1 = new Person();
var p2 = new Person();
p1.name.push( "zhangsan" );
p2.name.push( "lisi" );
p1.getInfo();
p2.getInfo();

使用原型+构造函数方式来定义对象,对象之间的属性互不干扰,各个对象间共享同一个方法,这是一种比较好的方式。

v)动态原型方式

JavaScript

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Person(){
   this .name = "zhangsan" ;
   this .password = "123" ;
   if ( typeof Person.flag == "undefined" ){
     alert( "invoked" );
     Person.prototype.getInfo = function (){
       alert( this .name + "," + this .password);
     }
     Person.flag = true ;
   }   
}
  
var p1 = new Person();
var p2 = new Person();
p1.getInfo();
p2.getInfo();

在动态原型方式中,在构造函数中通过标志量让所有对象共享一个方法,而每个对象拥有自己的属性。上面代码在第一次创建对象时,首先通过一个判断语句,看flag属性是否已经定义,若没有定义,则通过原型方式添加getInfo方法,然后将flag设置为true,那么当第二次创建对象时,if语句判断为假,跳过执行。这样就达到了我们所期望的结果,创建的对象属性是互不干扰的,而对象的方法是共享的。

17、JavaScript中对象的继承(5种方式)

第一种方式:对象冒充

冒充对象继承

JavaScript

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//父类
function Parent(username) {
   this .username = username;
   this .sayHello = function () {
     alert( this .username);
   };
}
//子类
function Child(username,password){
   //下面三行代码是最关键的
   this .method = Parent;
   this .method(username);
   delete this .method;
  
   this .password = password;
   this .sayWorld = function () {
     alert( this .password);
   };
}
  
var p = new Parent( "zhangsan" );
var c = new Child( "lisi" , "123" );
  
p.sayHello();
c.sayHello();
c.sayWorld()

第二种方式:call()

继承的第二种实现方式,call方法方式,call方法是Function对象中定义的方法,因此我们定义的每个函数都拥有该方法。call方法的第一个参数会被传递给函数中的this,从第2个参数开始,逐一赋给函数中的参数。

call 继承父类

JavaScript

?
1
2
3
4
5
6
7
function test(str) {
   alert( this .name+ "," +str);
}
var object = new Object();
object.name = "zhangsan" ;
//test.call相当于调用了test函数
test.call(object, "html5war" ); //将object赋给了this

接下来我们用call方式实现对象的继承

JavaScript

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//父类
function Parent(username){
   this .username = username;
   this .sayHello = function () {
     alert( this .username);
   };
}
//子类
function Child(username,password) {
   Parent.call( this ,username);
   this .password = password;
   this .sayWorld = function () {
     alert( this .password);
   };
}
  
var p = new Parent( "zhangsan" );
var c = new Child( "lisi" , "123" );
p.sayHello();
c.sayHello();
c.sayWorld();

第三种方式:apply()

apply 继承父类

JavaScript

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//父类
function Parent(username){
   this .username = username;
   this .sayHello = function (){
     alert( this .username);
   };
}
//子类
function Child(username,password){
   Parent.apply( this , new Array(username));
   this .password = password;
   this .sayWorld = function (){
     alert( this .password);