在劫

吾生也有涯,而知也无涯 。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Javascript是基于对象和事件驱动的脚本语言,主要应用在客户端。
特点:
交互性(信息的动态交互)
安全性(不可以直接访问本地硬盘)
跨平台性(只要是可以解析js的浏览器都可以执行,和平台无关)
JavaScript 是基于对象的,java是面向对象
JavaScript只需解析就可以执行,而java需要先编译成字节码文件,再执行。
JavaScript 是一种弱类型语言,java是强类型语言。
HTML的script标签用于把 JavaScript 插入 HTML 页面当中
编写JavaScript 两种方式:内部JS和外部JS

内部JS程序,在HTML源码中
     <script type="text/javascript">
		alert(1);
	</script>

外部JS程序,在HTML中引入单独的JS程序
     <script src="1.js"></script>
     1.js 内容
     alert(2);
	  </script>
在引用外部JS的script标签间不能编写JavaScript代码
Style标签可以放在任意的位置。

定义变量

使用
var 变量名 
定义变量

JavaScript中变量的数据类型是由JS引擎决定的

 var name="...";//name是string类型
 var age=24;//age是number类型
 var flag=true;//flag是boolean类型
 var email;//email只是声明,没有赋值,因此代表的类型是"undefined",也就是无法确定
 name=10;//name自动变成了number类型

使用typeof关键字查看变量代表的具体数据类型

 var sTemp = "test string";
 alert (typeof sTemp);    //输出 "string"
 alert (typeof 86);    //输出 "number"

JavaScript的数据类型
JavaScript包含两种不同数据类型:基本数据类型和引用数据类型。基本类型指的是简单的数据,引用类型指由多个值构成的对象

    undefined - 如果变量是 Undefined 类型的
    boolean - 如果变量是 Boolean 类型的
    number - 如果变量是 Number 类型的
    string - 如果变量是 String 类型的
    object - 如果变量是一种引用类型或 Null 类型的

String是基本数据类型,是值传递。

var a = "myobject";
a.name = "myname";//为字符串a动态添加name属性
alert("a.name="+a.name); //访问a的name属性,结果显示:a.name=undefined

String无法当作一个对象来处理。这也证明了一点:基本类型虽然也可以添加属性,也不会报错,经测试添加完之后却是无法访问的,实际上,javascript里的String是不可以改变的,javascript也没有提供任何一个改变字符串的方法和语法。
var b = "myobject";
b = b.substring(3,5);
alert("b="+b); // b=bj

并有改变String字符串"myobject",只b引用了另一个字符串"bj","myobject"被回收了
String实际上并不符合上面两种数据类型分类。它是具有两方面属性介于两都之间的一种特殊类型。

Null类型只有一个专用值 null,值 undefined 实际上是从值 null 派生来的,因此 ECMAScript 把它们定义为相等的

   <script type="text/javascript">
       alert("null == undefined的结果是:"+(null == undefined));  //输出 "true"
   </script>

NULL是不存在,而UNDEFINED是没有属性。
尽管这两个值相等,但它们的含义不同。undefined 是声明了变量但未对其初始化时赋予该变量的值,null 则用于表示尚未存在的对象(typeof 运算符对于 null 值会返回 "Object"。)
Undefined 类型
Undefined 类型只有一个值,即 undefined。当声明的变量未初始化时,该变量的默认值是 undefined

var oTemp;

当函数无明确返回值时,返回的也是值 "undefined",如下所示:

 function testFunc() { 
     //这是一个空函数,没有返回值
 }
 alert("testFunc() == undefined的结果是:"+(testFunc() == undefined)); //输出 "true"

引用数据类型
javascript引用数据类型是保存在堆内存中的对象,JavaScript不允许直接访问堆内存空间中的位置和操作堆内存空间,只能通过操作对象在栈内存中的引用地址。所以引用类型的数据,在栈内存中保存的实际上是对象在堆内存中的引用地址。通过这个引用地址可以快速查找到保存在堆内存中的对象。

<script type="text/javascript">
    var obj1 = new Object();
    var obj2 = obj1;
    obj2.name = "hehe";
    alert(obj1.name); // hehe
</script>

一般而言,基本数据类型是由固定数目的字节组成,这些字节可以在解析器的较底层进行操作,比如Number和 Boolean;而引用数据类型,可以包含任意数目的属性和元素,因此它们无法像基本数据类型那样很容易的操作。由于,引用数据类型的值是会发生变化的, 所以通过跟基本数据类型一样的值传递方式,也就没什么意义了,因为会牵涉到大量的内存的复制和比较,效率太低。所以引用数据类型是通过引用传递方式,实际传递的只是对象的一个地址。比如Array和Function,因为它们都是特殊的对象所以它们都是引用类型。另外,引用类型是可以添加属性,基本类型虽然也可以添加属性,也不会报错,经测试添加完之后却是无法访问的。

在JavaScript 中,逻辑NOT运算符与C和Java中的逻辑 NOT 运算符相同,都由感叹号(!)表示。与逻辑 OR 和逻辑 AND 运算符不同的是,逻辑 NOT 运算符返回的一定是 Boolean 值。
逻辑 NOT 运算符的行为如下:

    如果运算数是对象,返回 false
    如果运算数是数字 0,返回 true
    如果运算数是 0 以外的任何数字,返回 false
    如果运算数是 null,返回 true
    如果运算数是 NaN,返回 true
    如果运算数是 undefined,发生错误
document.writeln("oNaN=parseInt(\"abc\")返回的结果是"+oNaN);
document.writeln("bool类型的数false与!运算符运算之后的结果是:" + (!bFalse));
document.writeln("字符串sRed与!运算符运算之后的结果是: " + (!sRed));
document.writeln("数字0与!运算符运算之后的结果是:" + (!iZero));//如果运算数是数字 0,返回 true 
document.writeln("数字345与!运算符运算之后的结果是:" + (!iThreeFourFive));//如果运算数是 0 以外的任何数字,返回 false 
document.writeln("对象oObject与!运算符运算之后的结果是:" + (!oObject));//如果运算数是对象,返回 false 
document.writeln("NaN与!运算符运算之后的结果是:" + (!oNaN));//如果运算数是NaN,返回 true 
document.writeln("null与!运算符运算之后的结果是:" + (!oNull));//如果运算数是 null,返回 true 
document.writeln("undifined与!运算符运算之后的结果是:" + (!oUndefined));
//document.writeln("未定义的字符串sBule与!运算符运算之后的结果是:" + (!sBule));//sBule前面没有定义,也就是sBule运算数是 undefined,因此这里发生错误 

判断JavaScript变量的Boolean 值时,也可以使用逻辑NOT运算符。这样做需要在一行代码中使用两个 NOT 运算符。无论运算数是什么类型,第一个NOT运算符返回 Boolean值,第二个NOT将对该Boolean值取反,从而给出变量真正的Boolean值。使用not运算符判断JavaScript变量的Boolean值是一个非常有用的技巧,只要知道了变量的boolean值,那么当使用变量进行&&或者||运算时,就可以很快知道运算的结果了。

<script type="text/javascript">
     var bFalse = false;//运算数是bool类型的数
     var sRed = "red";//运算数是字符串
     var iZero = 0;//运算数是0
     var iThreeFourFive = 345;//运算数是 0 以外的任何数字
     var oObject = new Object();//对象
     var oNull=null;//运算数是null
     var oUndefined;//运算数是undifined
     var oNaN=parseInt("abc");//使用parseInt方法把尝试字符串abc转换成整数,因为abc不是数字,因此是转不了的,所以返回的结果就是NaN
    /*
    判断JavaScript 变量的 Boolean 值时,也可以使用逻辑 NOT 运算符。这样做需要在一行代码中使用两个 NOT 运算符。
    无论运算数是什么类型,第一个 NOT 运算符返回 Boolean 值。第二个 NOT 将对该 Boolean 值取反,从而给出变量真正的 Boolean 值。
    */
    document.write("<PRE>");
    document.writeln("布尔数false 的逻辑值是 " + (!!bFalse));
    document.writeln("字符串sRed 的逻辑值是 " + (!!sRed));
    document.writeln("数字0 的逻辑值是 " + (!!iZero));
    document.writeln("数字345 的逻辑值是 " + (!!iThreeFourFive));
    document.writeln("对象Object 的逻辑值是 " + (!!oObject));
    document.writeln("NaN的逻辑值是 :" + (!!oNaN));
    document.writeln("null 的逻辑值是 " + (!!oNull));
    document.writeln("undefined 的逻辑值是 " + (!!oUndefined));
    document.write("</PRE>");
  </script>

逻辑And运算符详解
逻辑AND运算的运算数可以是任何类型的,不止是Boolean值,如果某个运算数不是原始的Boolean型值,逻辑AND运算并不一定返回Boolean值
逻辑AND运算符的运算行为如下:

    如果一个运算数是对象,另一个是 Boolean 值,返回该对象。
    如果两个运算数都是对象,返回第二个对象。
    如果某个运算数是 null,返回 null。
    如果某个运算数是 NaN,返回 NaN。
    如果某个运算数是 undefined,发生错误。
    如果两个运算数都是boolean类型,则返回boolean值

JavaScript 中的逻辑AND运算也是简便运算,即如果第一个运算数决定了结果,就不再计算第二个运算数
值是 undefined,不能用于逻辑 AND 运算

 var bTrue = false;
 var bResult = (bTrue && bUnknown); //不会发生错误
 alert("bTrue && bUnknown的结果是:"+(bResult));//输出 "false" ,使用&&符号就可以

逻辑OR运算符
在JavaScript中,逻辑OR运算符用||表示

 var bTrue = true;
 var bFalse = false;
 var bResult = bTrue || bFalse;

在JavaScript中,0,"",false,null,undefined,NaN均表示false
JavaScript的逻辑 OR 运算也是简便运算,对于逻辑 OR 运算符来说,如果第一个运算数值为 true,就不再计算第二个运算数,如果某个运算数不是 Boolean 值,逻辑 OR 运算并不一定返回 Boolean 值,逻辑||的运算规则如下:

    如果一个运算数是对象,另一个是 Boolean 值,返回该对象。
    如果两个运算数都是对象,返回第一个对象。
    如果某个运算数是 null,返回 null。
    如果某个运算数是 NaN,返回 NaN。
    如果某个运算数是 undefined,发生错误。

Javascript中=的区别
JavaScript"=="的作用

    当==两边的内容是字符串时,则比较字符串的内容是否相等。
    当==两边的内容是数字时,则比较数字的大小是否相等。
    当==两边的内容是对象或者是对象的函数属性时,则比较内存地址是否相等。

=的区别
用于一般比较,=用于严格比较,在比较的时候可以转换数据类型,=严格比较,只要类型不匹配就返回flase

<script type="text/javascript">
    alert("\"1\"==true的结果是:"+("1"==true));
    alert("\"1\"===true的结果是:"+("1"===true));
    alert("\"1\"==1的结果是:"+("1"==1));
    alert("\"1\"===1的结果是:"+("1"===1));
 </script>

"1" == true类型不同,""将先做类型转换,把true转换为1,即为 "1" == 1;此时,类型仍不同,继续进行类型转换,把"1"转换为1,即为 1 == 1;此时,"" 左右两边的类型都为数值型,比较成功!
"1" === true 左侧为字符型,右侧为bool布尔型,左右两侧类型不同,结果为false;
"1" === 1 左侧为字符型,右侧为int数值型,左右两侧类型不同,结果为false;

==和===的区别:"==" 只要求值相等; "===" 要求值和类型都相等 

JavaScript判断数据类型
JS中的数据类型

   1.数值型(Number):包括整数、浮点数。
   2.布尔型(Boolean)
   3.字符串型(String)
   4.对象(Object)
   5.数组(Array)
   6.空值(Null)
   7.未定义(Undefined)

判断一个变量的数据类型:
数值型

 function isNumber(val){
      return typeof val === 'number';
 }

有些情况就不行,比如:

var a;
alert(isNumber(parseInt(a)));

实际上变量a是NaN,它是不能用于数值运算的

 function isNumber(val){
      return typeof val === 'number' && isFinite(val);
 }

JavaScript isFinite() 函数,isFinite() 函数用于检查其参数是否是无穷大,如果 number 是有限数字(或可转换为有限数字),那么返回 true。否则,如果 number 是 NaN(非数字),或者是正、负无穷大的数,则返回 false。
布尔型

/*
判断变量val是不是布尔类型
*/
function isBooleanType(val) {
    return typeof val ==="boolean";
}

字符串(String)

/*
判断变量是不是字符串类型
*/
function isStringType(val) {
    return typeof val === "string";
}

未定义(Undefined)

/*
判断变量是不是Undefined
*/
function isUndefined(val) {
    return typeof val === "undefined";
}

对象(Object)
由于当变量是空值Null时,typeof也会返回object,所以Object不能直接用 typeof 判断。

function isObj(str){
    if(str === null || typeof str === 'undefined'){
        return false;
    }
    return typeof str === 'object';
}

空值(Null)
判断空值用 val === null 即可

 function isNull(val){
       return  val === null;
 }

数组(Array)
数组类型不可用typeof来判断。因为当变量是数组类型是,typeof会返回object.
有两种方法判断数组类型

/*判断变量arr是不是数组
方法一
*/
function isArray1(arr) {
    return Object.prototype.toString.apply(arr) === '[object Array]';
}

/*判断变量arr是不是数组
方法二
*/
function isArray2(arr) {
    if(arr === null || typeof arr === 'undefined'){
        return false;
    }
    return arr.constructor === Array;
}

JavaScript函数
JavaScript函数的分类
  1、自定义函数(我们自己编写的函数),如:function funName(){}
  2、系统函数(JavaScript自带的函数),如alert函数。
函数的调用方式
1、普通调用:functionName(实际参数...)
2、通过指向函数的变量去调用

var myVar=函数名;
myVar(实际参数...);

函数返回值

 1.当函数无明确返回值时,返回的值就是"undefined"。
 2.当函数有返回值时,返回值是什么就返回什么。

<script type="text/javascript">
    var str="window.alert('hhe');";
    eval(str);//eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。
    /*自定义函数*/
    function test(str){
        alert(str);
    }
    window.alert(test);//输出test函数的定义

    //函数的调用方式1
    test("hhe");

    //函数的调用方式2
    var myFunction=test;
    myFunction("sse");

    window.alert(myFunction);
    /*当函数无明确返回值时,返回的也是值 "undefined"*/
    var retVal=test("test");//test函数执行完之后,并没有返回值,因此retVal变量接收到的返回值结果是undefined
    alert("retVal="+retVal);//输出undefined
  </script>

函数的深入使用
可变参数
 函数的参数列表可以是任意多个,并且数据类型可以是任意的类型,JavaScript的函数天然支持可变参数,JavaScript有一个arguments变量可以访问所有传到函数内部的参数。

<script type="text/javascript">
    /*add函数是一个参数可变的函数*/
    function add(){
        var result=0;
        for(var i=0;i<arguments.length;i++){
            //alert(arguments[i]);
            result+=arguments[i];
        }

        return result;
    }
    alert("add(1,2,3)="+add(1,2,3));//调用add函数时传入3个参数
    alert("add(1,2,3,4,5,6)="+add(1,2,3,4,5,6));//调用add函数时传入6个参数
    alert("add()="+add());//调用add函数时不传入参数
    alert("add(1,\"HelloWorld\")="+add(1,"HelloWorld"));//调用add函数时传入不同类型的参数
  </script>

javascript创建动态函数
avaScript支持创建动态函数,动态函数必须用Function对象来定义(Function是javascript中的一个对象,是固定不变的,规定Function对象的"F"必须大写,当是function的时候,我们知道是定义函数的时候所使用的一个关键字:function funName(x,y),当是Function的时候(F大写的时候),我们知道是javascript中的对象)
创建动态函数的基本格式:var 变量名 = new Function("参数1","参数2","参数n","执行语句");
使用new关键字(new是javascript中一个关键字,也是固定的,我们在定义动态函数的时候必须要使用new来创建这个Function对象)
我们先定义一个变量: var 变量名,在这里,变量名是随便的,然后我们再使用new关键字创建一个Function对象,然后再把这个对象赋值给这个任意的变量,也就是:var 变量名 = new Function("参数1","参数2","参数n","执行语句");Function后面的括号里先是传递给函数的参数,然后用一个逗号(,)隔开然后是这个函数要执行的功能的代码

 <script type="text/javascript">
     var square = new Function ("x","y","var sum ; sum = x+y;return sum;");
     alert("square(2,3)的结果是:"+square(2,3)); //输出5
   </script>

等同于:

 function square (x,y){
      var sum;
      sum = x+y;
      return sum;
 }

匿名函数

 var f1 = function(i1, i2) {
      return i1 + i2;
 }
 alert(f1(1,2));


alert(function(i1, i2) { return i1 + i2; }(10,10));

JavaScript不支持函数的重载
JavaScript没有方法重载的说法,如果两个方法名字一样,即使参数个数不一样,那么后面定义的就会覆盖前面定义,调用方法时永远是调用后定义的那个。

JavaScript数组
JavaScript中的Array对象就是数组,首先是一个动态数组,无需预先制定大小,而且是一个像Java中数组、ArrayList、Hashtable等的超强综合体
常规方式声明:

1、var arrName = new Array();//创建一个数组
2、var arrName = new Array([size]); //创建一个数组并指定长度,注意不是上限,是长度
3、var arrName =new Array("孤傲苍狼","白虎神皇","灭世魔尊");//创建一个数组,并初始化数组的内容
注意:虽然var arrName = new Array([size]);指定了长度,但实际上所有情况下数组都是变长的,也就是说即使指定了长度为2,仍然可以将元素存储在规定长度以外的,注意:这时长度会随之改变。

Array的简化声明:

普通数组初始化:var arr = [3, 5, 6, 8, 9];

澄清概念
  1.JS中"基于对象=面向对象"
  2.JS中没有类(Class),但是它取了一个新的名字叫“原型对象”,因此"类=原型对象"
类(原型对象)和对象(实例)的区别与联系
  1.类(原型对象)是抽象,是概念的,代表一类事物。
  2.对象是具体的,实际的,代表一个具体的事物。
  3.类(原型对象)是对象实例的模板,对象实例是类的一个个体。
JavaScript面向对象三大特征:
1.封装
封装就是把抽象出来的属性和对属性的操作封装在一起,属性被保护在内部,程序的其它部分只有通过被授权的操作(函数),才能对属性进行操作
2.继承

<script type="text/javascript">
    /*定义Stu类*/
    function Stu(name,age){
        this.Name=name;
        this.Age=age;
        this.Show=function(){
            window.alert("我的名字是:"+this.Name+",今年:"+this.Age);
        }
        this.SayHello = function(){
            window.alert("Hello,"+this.Name);
        }
    }

    /*定义MidStu类*/
    function MidStu(name,age){
        this.stu=Stu;//MidStu类继承Stu类
        this.stu(name,age);//JS中实际上是通过对象冒充来实现继承的,这句话不能少,因为JS是动态语言,如果不执行,则不能实现继承效果
        /*
        从父类继承下来的公共方法,可以根据实际情况选择重写
        */
        //在子类MidStu中重写父类Stu的Show方法
        /*this.Show=function(){
            alert("MidStu.Show()");
        }*/
        //在子类MidStu中重写父类Stu的SayHello方法
        this.SayHello=function(){
            alert("你好,"+this.Name);
        }

    }

    var midStu = new MidStu("孤傲苍狼",24);//创建一个MidStu类实例对象
    alert("访问继承下来的属性Name和Age,midStu.Name="+midStu.Name+",midStu.Name="+midStu.Age);//访问继承下来的属性
    midStu.Show();//调用从父类Stu继承下来的Show方法
    midStu.SayHello();//调用从父类Stu继承下来的SayHello方法,SayHello()在子类中进行了重写,这里调用的是重写过后的SayHello()方法
  </script>

3.多态
所谓多态,就是指一个引用在不同情况下的多种状态,在Java中多态是指通过指向父类的引用,来调用不同子类中实现的方法。
JS实际上是无态的,是一种动态语言,一个变量的类型是在运行过程中由JS引擎决定的,所以说,JS天然支持多态。

JavaScript自定义类(原型对象)的方式
工厂方法——使用new Object创建对象并添加相关属性

//通过Object直接创建对象
    //var p1 = new Object();//创建一个Object对象
    var p1 = {};//创建一个Object对象,简写
    //动态增加属性、方法
    p1.Name = "hehe";
    p1.Age = 24;
    p1.SayHello = function() { alert("hello,"+p1.Name); };
    p1.SayHello();  
    for(var propertyName in p1) {//对象的成员都是对象的key
        alert(propertyName);
    }

使用构造函数来定义类(原型对象)

function 类名(){
     this.属性名;//公共属性
     var 属性名;//私有属性
     /*凡是定义类的公共属性和公共方法都要使用this*/
     //定义类的公共函数
     this.函数名=function(){
                
     }
     //定义类的私有函数
     function 函数名(){

     }
}
/*定义一个猫类,这种就是使用构造函数来定义类(原型对象)*/
    function Cat(){
        this.Name="catName";//public属性
        this.Age;//public属性
        this.Color;//public属性
        var weight=2;//private属性,只能在Cat类内部使用,Cat类的对象无法访问这个私有属性
        //public方法
        this.publicFunction = function(){
            alert(weight);
            alert("猫叫...");
        }
        //private方法,只能在Cat类内部使用,Cat类的对象无法访问这个私有方法
        var privateFunction = function(){
            alert("私有方法");
        }


    }
    //如果这样用,那么就当成函数来使用
    Cat();
    //如果这样用,那么就当成类来使用
    var cat1 = new Cat();
    //cat1就是一个对象(实例)
    alert(cat1.Name);//访问公共属性,弹出默认值catName
    cat1.Name="TomCat";//访问公共属性
    cat1.Age=3;//访问公共属性
    cat1.Color="白色";//访问公共属性
    alert(cat1.weight);//访问私有属性,无法访问,弹出undefined
    alert(cat1.Name+"\t"+cat1.Age+"\t"+cat1.Color);//访问对象的属性方式1:对象名.属性名
    alert(cat1["Name"]+"\t"+cat1["Age"]+"\t"+cat1["Color"]);//访问对象的属性方式2:对象名["属性名"]
    cat1.publicFunction();//调用public方法
    cat1.privateFunction();//调用private方法,报错:对象不支持此属性或方法
    for(var property in cat1){
        document.writeln(property+"\t");
    }

this关键字

<script type="text/javascript">
    function Person(){
        /*使用var 属性名定义的属性是类的私有属性,外界无法访问,要想被外界访问,就要使用公共方法*/
        var QQ="123456"; 
        var Email="123456@qq.com";

        /*使用this.属性名定义的属性就是类的公共属性,是可以被外界访问的*/
        this.Name="141";
        this.Age=24;

        /*定义Person类的公共方法,凡是定义类的公共属性和公共方法都要使用this*/
        this.Show=function(){//定义Person类的公共方法(特权方法)
            alert("QQ="+QQ+"\tEmail="+Email);

        }
        
        /*定义Person类的私有方法*/
        function Show2(){//这是Person类的一个私有方法,只能在Person类内部使用
            
        }
    }

    var p1 = new Person();
    alert("私有属性p1.QQ="+p1.QQ+"\t"+"p1.Email="+p1.Email);
    alert("公共属性p1.Name="+p1.Name+"\t"+"p1.Age="+p1.Age);
    p1.Show();
    //p1.Show2();//这里会报错,无法调用Person类的私有方法,
    
    /*
    Window 对象描述
    Window 对象表示一个浏览器窗口或一个框架。在客户端 JavaScript 中,Window 对象是全局对象,所有的表达式都在当前的环境中计算。
    也就是说,要引用当前窗口根本不需要特殊的语法,可以把那个窗口的属性作为全局变量来使用。例如,可以只写 document,而不必写 window.document。

    同样,可以把当前窗口对象的方法当作函数来使用,如只写 alert(),而不必写 Window.alert()。
    */
    function Test(){
        alert(this.v);
    }
    v=90;
    Test();
    window.Test();//记住一句话:哪个对象调用this所在的函数,那么this代表的就是哪个对象实例,这里是window对象调用Test()方法,因此此时this指的就是window对象

    function Test2(){
        this.fnTest=function(){
            alert(this.v2);
        }
    }

    var t = new Test2();
    t.v2="记住一句话:哪个对象调用this所在的函数,那么this代表的就是哪个对象实例";
    t.fnTest();//这里是t对象调用Test()方法,因此此时this指的就是t对象
  </script>

1、this不能在类定义的外部使用,只能在类定义的内部使用。
2、哪个对象调用this所在的函数,那么this代表的就是哪个对象实例。

Object对象
Object类是所有JavaScript类的基类(父类),提供了一种创建自定义对象的简单方式,不再需要程序员定义构造函数
Object类主要属性
  1.constructor:对象的构造函数。
  2.prototype:获得类的prototype对象,static性质。
Object类主要方法:

hasOwnProperty(propertyName): 判断对象是否有某个特定的属性。必须用字符串指定该属性,例如,obj.hasOwnProperty("name"),返回布尔值。此方法无法检查该对象的原型链中是否具有该属性;该属性必须是对象本身的一个成员。

isPrototypeOf(object):判断该对象是否为另一个对象的原型

propertyIsEnumerable(propertyName):过这个方法我们可以检测出这个对象成员是否是可遍历的,如果是可遍历出来的,证明这个对象就是可以利用for in 循环进行遍历的,
  格式如下:obj.propertyIsEnumerable(propertyName)

JavaScript编写类
构造函数方式:

用构造函数模拟"类",在其内部用this关键字指代实例对象。
基本语法:
function 类名(){
     this.属性名;//公共属性
     var 属性名;//私有属性
    /*凡是定义类的公共属性和公共方法都要使用this*/
    //定义类的公共函数
    this.函数名=function(){
            .....
    }
    //定义类的私有函数
    function 函数名(){
    ......
    }
}
/*定义一个Person类*/
    function Person(_name,_age,_salary){
        //Person类的公开属性,类的公开属性的定义方式是:”this.属性名“
        this.name=_name;
        //Person类的私有属性,类的私有属性的定义方式是:”var 属性名“
        var age=_age;//私有属性
        var salary=_salary;//私有属性

        /*定义私有属性Age的对外公开访问方法*/
        this.setAge = function(intAge) {
            age = intAge;
        }
        /*定义私有属性Age的对外公开访问方法*/
        this.getAge = function() {
            return age;
        }

        //定义Person类的公开方法(特权方法),类的公开方法的定义方式是:”this.functionName=function(){.....}“
        this.Show=function(){
            document.writeln("在公开方法里面访问类的私有属性是允许的,age="+age+"\t"+"salary="+salary);//在公开方法里面访问类的私有属性是允许的
        }
        //公共方法
        this.publicMethod = function(){
            document.writeln("在公开方法里面访问类的私有方法是允许的");
            privateFn();//在公开方法里面调用类的私有方法
            privateFn2();//在公开方法里面调用类的私有方法
        }
        /*
        定义Person类的私有方法(内部方法),
        类的私有方法的定义方式是:”function functionName(){.....}“,
        或者 var functionName=function(){....}
        */
        function privateFn(){
            document.writeln("我是Person类的私有函数privateFn");
        }

        var privateFn2=function(){
            document.writeln("我是Person类的私有函数privateFn2");
        }
    }

原型方式
需要说明的是,使用原型方式编写JavaScript类是无法给类添加私有属性和私有方法的,使用原型方式添加的属性和方法都是public的

方法一:

/*定义一个Person类*/
    function Person(_name,_age,_weight,_height){
       this.init(_name,_age,_weight,_height);
    }

    /*使用原型的方式定义Person类的public属性:name,age,weight,height,使用原型的方式添加的属性都是public的*/
    Person.prototype.name;
    Person.prototype.age;
    Person.prototype.weight;
    Person.prototype.height;
    /*使用原型的方式给Person类添加public方法,使用原型的方式添加的方法都是public的*/
    /*使用原型的方式给Person类添加init方法*/
    Person.prototype.init = function(_name,_age,_weight,_height) {
        if(_name != undefined && _age!=undefined && _weight!=undefined && _height!=undefined){
            this.name = _name;
            this.age = _age;
            this.weight=_weight;
            this.height=_height;
            document.writeln("this.name="+this.name+",this.age="+this.age+",this.weight="+this.weight+",this.height="+this.height);
        }
         
    }
    /*使用原型的方式给Person类添加show方法*/
    Person.prototype.show = function(){
        document.writeln("show method");
    }


方法二:

/*定义类Person2*/
    function Person2(){
        
    }

    /*使用原型方式给类定义public属性和public方法更加优雅的写法*/
    Person2.prototype = {
        name:"",//public属性
        age:0,//public属性
        weight:0,//public属性
        height:0,//public属性
        /*public方法*/
        init:function(_name,_age,_weight,_height) {
            this.name = _name;
            this.age = _age;
            this.weight=_weight;
            this.height=_height;
            document.writeln("this.name="+this.name+",this.age="+this.age+",this.weight="+this.weight+",this.height="+this.height);
        },
        /*public方法*/
        show:function(){
            document.writeln("show method");
        }
    };

原型方式的优点:所有对象实例都共享类中定义的方法,这样就没有造成内存浪费。缺点,第一,不能定义类的私有属性和私有方法,第二,给在创建对象,给对象的属性初始化时,需要额外写一个初始化对象的方法。
构造函数+原型
构造函数方式和原型方式都有各自的优缺点,因此可以把这两种方式合并起来,用构造函数方式来定义类的属性(public属性,private属性),用原型方式来定义类的方法(public方法)。互补不足,这就有了第三种写法。

/*定义一个Person类*/
    function Person(_name,_age,_salary){
        //在Person类内部定义类的public属性和private属性以及private方法
        //Person类的公开属性,类的公开属性的定义方式是:”this.属性名“
        this.name=_name;
        //Person类的私有属性,类的私有属性的定义方式是:”var 属性名“
        var age=_age;//私有属性,只能在类内部使用
        var salary=_salary;//私有属性,只能在类内部使用
        /*
        定义Person类的私有方法(内部方法),只能在类内部使用
        类的私有方法的定义方式是:”function functionName(){.....}“,
        或者 var functionName=function(){....}
        */
        function privateFn(){
            document.write("<pre>");
            document.writeln("我是Person类的私有属性age,只能在Person类内部使用,初始化后age="+age);
            document.writeln("我是Person类的私有函数privateFn,只能在Person类内部使用");
            document.write("</pre>");
        }

        var privateFn2=function(){
            document.write("<pre>");
            document.writeln("我是Person类的私有属性salary,只能在Person类内部使用,初始化后salary="+salary);
            document.writeln("我是Person类的私有函数privateFn2,只能在Person类内部使用");
            document.write("</pre>");
        }

        privateFn();//在Person类内部调用私有方法
        privateFn2();//在Person类内部调用私有方法
    }

    //使用prototype原型方式定义的方法(public方法)是无法访问类的私有属性和私有方法的
    //使用prototype原型方式定义Person类的方public方法
    Person.prototype={
        setName:function(_name){
            this.name = _name;
            //privateFn();//不能调用Person类定义的私有方法privateFn(),会报错:缺少对象
        },
        getName:function(){
            return this.name;
        },
        show:function(){
            document.writeln("公开方法show");
        },
        //公共方法
        publicMethod:function(){
            document.writeln("公开方法publicMethod");
        }
    };

扩展JavaScript内置类,添加动态方法:

  类名.prototype.方法名 = function([param1],[param2],....[paramn]) {
    .................
  }
  [param1],[param2],....[paramn]这些参数都是可选的
  使用这种方式给类添加的扩展方法都是动态的,动态方法是针对类的实例对象的,所以调用必须要用"对象.方法名"的形式去调用,不能用"类名.方法名"的形式去调用!

使用prototype属性扩展String类

/*扩展为String类,为String类增加quote(两边加字符)方法*/
        String.prototype.quote = function(quotestr) {
            if (!quotestr) {
                quotestr = "\"";
            }
            return quotestr + this + quotestr;
        };

使用prototype扩展Number类

 Number.prototype.add=function(n){
     //哪个对象调用this所在的函数,那么this代表的就是哪个对象实例
     return this+n;
 }

使用prototype扩展Array类

Array.prototype.findVal=function(val){
        var index=-1;
        //哪个对象调用this所在的函数,那么this代表的就是哪个对象实例
        for(var i=0;i<this.length;i++){
            if(val==this[i]){
                index=i;
                break;
            }
        }
        return index;
    }

扩展JavaScript内置类,添加静态方法

  JavaScript是可以给类添加静态的扩展方法的,语法格式如下:
  类名.方法名 = function([param1],[param2],....[paramn]) {
    .................
  }
  [param1],[param2],....[paramn]这些参数都是可选的
  使用这种方式给类添加的扩展方法都是静态的,动态方法是针对类的实例对象的,所以调用必须要用"对象.方法名"的形式去调用,而静态方法是针对类的,用"类名.方法名"的形式去调用!

闭包
  在JavaScript中,变量的作用域分两种:全局变量和局部变量。
  在Javascript中,在函数内部可以直接读取全局变量。

 var n=999;//定义全局变量n
 function f1(){
   alert("在函数内部访问全局变量n,n="+n);//在函数内部访问全局变量n
 }
 f1(); // 999

但是反过来则不行,在函数外部无法读取函数内的局部变量。

 function f1(){
    var n=999;//在f1函数内部定义局部变量n
  }
  alert("在函数外部访问局部变量n,n="+n); //在函数外部访问局部变量n,错误:n未定义

从外部读取局部变量
在函数的内部,再定义一个函数

function f1(){
  var n=999;//f1函数内部的局部变量n
    //在f1函数内部定义一个f2函数
  function f2(){
       //在f2函数内部是可以访问局部变量n的
    alert(n); // 999
  }
}
function f1(){
    var n=999;//局部变量n
    //在f1函数内部声明的f2函数
    function f2(){
      alert(n);
    }

    return f2;//将f2函数作为f1函数的返回值
  }
  var result=f1();//f1调用完后的返回值是一个f2函数,此时result就是f2函数
  result(); // 999,调用f2函数

JavaScript闭包就是在另一个作用域中保存了一份它从上一级函数或者作用域得到的变量,而这些变量是不会随上一级函数的执行完成而销毁.闭包就是能够读取其他函数内部变量的函数。由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中
使用闭包的注意点
1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

posted on 2017-09-11 18:18  长嘴大耳怪  阅读(141)  评论(0编辑  收藏  举报