javascript 基础

一  javascript 数据类型

 

        javascript属于弱类型语言 ,声明变量一概采用var关键字,变量的类型根据值类型自动匹配。 根据值类型可以javascript数据类型分为2类: 原始类型和引用类型。

        原始类型指变量在栈上分配空间,可以自动释放,不需要进行垃圾回收.它有5种类型:

1. undefined   2. null    3. string      4. number      5. boolean 

可以用typeof运算符来判断它们的基本类型如:

        var a;
        alert(typeof a); //undefinded
		
        a = 1;
        alert(typeof a); //number
		
        a = '1';
        alert(typeof a); //string
		
        a = true;
        alert(typeof a); //boolean
		
        a = null;
        alert(typeof a); //object

这里typeodf null 返回object, 可以把null理解成一个引用类型,只不过这个引用类型没有引用的对象而已,所以把它归为

原始类型。typeodf运算符对于引用类型都返回object. 当然typeof 还有一种类型就是function.

 

       引用类型指这个类型的变量在栈上分配但是它的值是一个地址,这个地址指向堆上的一个对象实例。所以引用类型所指向的都是一个对象。在javascript有一个Object类,它是所有类的父类。同时,javascript为string,number,boolean都提供了相应的包装类。

       可以用instanceof 判断变量的类类型如:

	var a = new Object();
	alert(a instanceof Object);  //true
		
	a = new String("1");
	alert(typeof a);            //object
	alert(a instanceof Object); //true
	alert(a instanceof String); //true
 

二  函数

 

       javascript中的函数灵活多变,但是它们终究都是一个对象。我们定义了一个函数,也就是生成了一个Function对象的实例。并把该对象.name设置为函数名,且把自己绑定倒当前环境下,在浏览器中为window对象,这也是为什么我们没有用引用变量指向它却可以调用它的原因。如:

   function Car(){ }
	alert(typeof Car);               //function
	alert(Car instanceof Object);    //true
	alert(Car instanceof Function);  //true
	alert(Car.name);                 //Car
	alert(window.Car === Car);       //true

 

        既然函数是一个对象,那么就可以将该对象赋值给一个变量。如果有一个变量指向了一个函数,我们就可以自己用该变量调用函数,而不需要函数名了,这样也就可以定义一个匿名函数了。如:

  var Car = function(){alert("Car function...")}
	alert(typeof Car);    //function;
	alert(Car instanceof Function); //true
	alert(Car.name); //""
	Car();

 

三  自执行函数

 

         一般的函数总是先定义,后调用。但是自执行函数是那种在定义跟调用合并的一种方式。如:

	(function Car(){alert("Car function...")})();
	alert(typeof Car);   //undefinded

        注意的是这里一定要()把函数定义包括起来,否则将出现错误。可以看到函数执行后,该函数并没有绑定到window下,所以这里的函数名没有任何意义,所以下面这种写法会更直观一点:

 

	(function(){
		alert("Car function...")
	}());

 

        那么这种写法有什么用呢:

1.   方便,定义完之后直接就用了,这个可能是其中一个原因把,不过可能性不太大。

2.   不影响全局对象如window,这里单指这个被()包括的函数,函数里面的代码实质上 仍然会影响window下的属性,因为内部 是可以访问全局变量的。

3.    提供一种命名空间的功能,使多库共存代码冲突降为最小。

 

四  作为对象方法的函数与this指针

 

        在javascript中除了构造函数,所有的函数都是作为一个对象的方法。也就是说,要么用new调用一个函数,要么用obj.method()来调用函数。那么this指针指的就是调用该方法的对象。

        那么alert方法为什么没有指明调用它的对象呢,因为alert属于window对象,window对象在浏览器中作为所有全局变量的绑定对象所以可以省略。

 

  	function funcA(){
		alert(this.name_for_test); 
	}
	
	funcA(); //undefined
	
	window.name_for_test = "window";
	funcA(); //window
	
	var obj = {name_for_test : "obj"};
	funcA.call(obj); //obj
 

五  构造函数与new

 

      其实任何一个函数都可以作为一个构造函数,只要它前面跟了一个new操作符。而new的目的是创建一个对象实例。但是javascript中没有类的概念,除了原始类型,一切都是对象。所以new的过程像是在申请内存然后copy原始对象属性的过程。

通过一个实例来说明可能会更好点:

 

function ClassA(){
		
		alert(this.type);
		this.name = "ClassA";
		var _name = "_ClassA";
		this.exist = "ClassA_exist";
	}
	
	/*  输出 ClassA,undefinded
	 *  
	 *  1. ClassA本身作为一个对象,已经在堆上分配到了内存。
	 *  2. 有了ClassA对象后,函数体里面的this就指ClassA对象,那么对this.xxx的赋值就像是对象属性的晚绑定。
	 *  3. var _name 作为一个局部变量在栈上分配,函数退出即释放空间,所以没有绑定到ClassA对象
	 */
	alert(ClassA.name);  //ClassA
	alert(ClassA._name); //undefinded
	
	ClassA._type = "_base";
	ClassA.prototype.type = "base";
	ClassA.prototype.exist = "ClassA_prototype_exist";
	
	/*
	 * new操作过程:
	 * 1. 生成空对象o
	 * 2. o.__proto__= ClassA.prototype,alert(this.type);用于测试2,3步哪步先执行
	 * 3. 执行构造函数,this指针指向生成的对象o
	 * 4. 如果构造函数没return 对象,则new运算的值为此生成对象o,否则为return的对象
	 */
    var objA = new ClassA();
	
	alert(objA.name);  //ClassA
	alert(objA._name); //undefinded
	alert(objA.type);  //base
	alert(objA._type); //undefinded, 因为属于构造函数之外的晚绑定,生成新对象时不执行此晚绑定
	alert(objA.exist); //ClassA_exist 因为查this下面的属性,找到了则不查__proto__下面的属性
	
	alert(objA.constructor.name); //ClassA

      可以看到创建一个对象实例基本在执行Copy操作,在java中有深浅拷贝,这里也一样。所以对于引用类型作为属性时,是需要注意的。

 

六  原型与原型链

 

       对于obj.name这么条语句,将会怎么查找这个name属性呢

1. 查找obj下面是否有name属性,有则返回,没有则tObj = obj.__proto__执行2

2. 如果tObj不为null,查找tObj下面是否有是否有name属性,有则返回,没有则tObj = tObj.__proto__执行2

可以看到没有找到name属性会一直遍历__proto__.__proto__.__proto__....的查下去,直倒查到或遇到一个__proto__=null

而Object.prototype.__proto__正好为null.这个查找链就是原型链。

 

       这里要区分类的原型跟对象实例的 原型。

类的原型即prototype属性,只有类有这个属性,它是作为对象的模板,相当于与java中的静态属性。所有同类型对象共享此数据。对其修改将会影响到所有对象。

对象实例的 原型即__proto__,在new的第2步操作中看到它会被赋值为类的prototype.这个属性一般不公开,但firefox下可以访问。

 

例1:对prototype或__proto__操作影响到所有对象:

 

	function ClassA(){}
	
	ClassA.prototype._name = "_classA";
	
	var objA = new ClassA();
	var objB = new ClassA();
	
	alert(objA._name); //_classA
	alert(objB._name); //_classA
	
	ClassA.prototype._name = "_classB";
	alert(objA._name); //_classB
	alert(objB._name); //_classB
	
	objA.__proto__._name = "_classA";
	alert(objA._name); //_classA
	alert(ClassA.prototype._name); //_classA
	alert(objB._name); //_classA
	alert(objB.__proto__._name); //_classA

 

例2: 原型链

 

	function ClassA(){}
	var objA = new ClassA();
	
	alert(Object.prototype.__proto__); //null
	//all true
	alert(objA.__proto__ === ClassA.prototype);
	alert(objA.__proto__.__proto__ === Object.prototype);
	alert(objA.__proto__.__proto__ .__proto__=== null);
 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值