JavaScript学习

  1. JavaScript是互联网上最流行的脚本语言,可嵌入html文档中,由浏览器解析运行,广泛应用于与web互联的PC、服务器、智能手机等设备。目前所有主流浏览器均可支持js语言。
  2. JavaScript一些简单函数运用及说明:
    <script>
        //js输出语句,括号内的html statement可以是html的任何合法语句,它会由浏览器按照html语法规则解析并显示出来
        document.write("html statement");
        //alert()函数,调用此函数可以使web页面弹出一个提示页面,提示页面上面可以是你想展示的一段话
        alert("some you want to show");
        //js语句使用下面的函数通过id寻找html页面上的元素,并使用自定义名称指代此元素
        xelement=document.getElementById("elementid");
        /*可通过js语句改变元素,如下面的函数,通过innerHTML字段赋值改变xelement此元素的包含的内容,值
        可以是任意合法的html语句(前提是xelement必须是一个容器元素,可包含值中的html元素)*/
        xelement.innerHTML="html statment";
        //js中的if-else语句
        if(condition){
            do_something 1;}
        else{
            do_something 2;}
        //在js中可以定义并使用函数名调用函数,定义函数需要使用关键字function
        function functionname(variable){
            function_content;
        }
        //js中使用Date()函数显示时间,下述语句即可在提示页面上显示当前时间
        alter(Date());
        //js中向控制台中写入数据可以使用函数console.log(),类似于java中的system.out.printf()函数
        console.log("data");
    </script>

     

  3. JavaScript中的变量及数据类型(初学,有很多不严谨和错误的地方,先不删):
    <script>
       //JavaScript是一个弱类型的编程语言,命名变量时无需指定其类型,在赋值之后由编译器自动识别,命名变量需要使用关键字"var"
       var x,y,a1,_table,b;//变量可以是以大小写字母或者"_"/"$"开头的字符串,一般命名规则遵循驼峰法
       //JavaScript内置数据类型有数字、字符串、数组、对象,boolean值,其各个创建方式如下:
       x=1.1e3;//数字类型(number),可以为整数、浮点数、或者科学计数法(e)
       y="aaa zzz";//字符串类型(string),使用双引号或者单引号包括
       //数组类型(array),使用中括号包括,内部元素可以为已定义变量或者其他数据类型常量(字面量),各元素之间使用","隔开
       a1=["a","b",x,y,1,2];
       //对象类型(object),即为用大括号包括起来的若干组key-value值对,每个key-value值对之间使用","隔开
       _table={First:x,Second:y,Third:a1,Forth:"undfined"};
       b=true;//boolean值只有true或者false两种
       document.write("x="+x+"<br>");
       document.write("y="+y+"<br>");
       document.write("a1="+a1+"<br>");
       document.write("_table="+_table+"<br>");
       /*JavaScript内置了若干种运算符,常见的有赋值运算符(=),算数运算符(+、-、*、/、%),
        逻辑运算符(==、!=),比较运算符(>、<)等
       JavaScript中可以使用关键字function定义一个函数,一个函数分为函数名、参数、函数体、返回值等
        几部分组成*/
       function functionname(variable1,variable2){
           //函数体
           return 0;//返回值
       }
       //JavaScript数据类型判定,js中可以使用typeof()函数来得到变量的类型,返回的类型有number、string、object等
       document.write("x的数据类型是"+typeof(x));//返回number
       /*TIP,注意typeof()函数不能判定一个数据类型是不是array类型(array类型变量返回值是object),想
        要判定一个变量是否是Array,可以使用Array.isArray(variable)函数*/
       document.write(Array.isArray(a1));//返回true
       /*TIP,有时候,同样可以使用instanceof关键字判定一个变量是不是某个类型,语法为
        variable instanceof type.prototype,此关键字使用较为复杂。 */
    </script>

     

  4. JavaScript中的数据类型:JS中的数据类型分为基本类型引用类型两种,基本类型6种:数字(Number)、字符串(String)、布尔(Boolean)、空类型(Null)、未定义(Undefined)、Symbol类型(表示独一无二的值);引用类型3种:对象(Object)、数组(Array)、函数(Function)。
  5. JavaScript中的数据类型:JS是一个弱类型的编程语言,定义变量时可以不为其指定类型,此时变量的类型是Undefined,但是定义变量时也可以使用关键字new为其指定类型,例:var x=new Array,即指定变量x是数组类型。变量x的类型随着赋值类型的不同也会不同,x=1(此时x的类型是number),x="1"(此时x的类型是string)。
  6. JavaScript变量简明内存结构:JS的变量内存模型与Java相似,对于基本数据类型,变量名变量值都是存放在栈内存(stack)中的,通过变量名改变变量值只是在栈内存中新建一个变量指向变量名,原来的变量值不变(当无变量名指向此值后可能会被垃圾回收机制处理掉);对于引用数据类型,实际变量存放在堆内存(heap)中,而栈内存中存放的是变量名和指向实际变量值的堆内存地址,因此通过变量名改变变量值会导致变量值本身的改变(非赋值操作,赋值操作会使变量名指向的堆内存地址改变,而不会改变原变量的值)。
  7. JavaScript中的对象:JS中的对象概念和Java中类似,但是细节处有很多不同,下面是一个js对象实例及其说明:
    <script>
        /*一个对象的创建:对象包括属性和方法两种元素,不管属性还是方法均使用"name:value"的方式定义,
        各属性/方法之间使用","隔开,所有属性使用"{}"包括*/
        var obj={
            property1:3.14e5,//定义一个数字属性
            property2:"1234567890",//定义一个字符串属性
            property3:[1,2,3,4,"5"],//定义一个Array属性
            property4:{name:"mike",age:18,gender:"male"},//定义另一个对象属性
            //定义一个方法需要使用关键字"function()",方法体使用大括号包括
            func1:function(){
                alert("这是一个方法");
            }
        }
        //----------------------------------------------------------------------------------
        //一个对象的使用:
        document.write(obj.property2);//调用一个属性值可以使用"objname.propertyname"的形式
        document.write("<br>");
        document.write(obj["property3"]);//还可以使用"objname["propertyname"]"的形式,注意属性名必须使用引号"包括
        document.write("<br>");
        document.write(obj.func1);//对于方法的引用,若方法名不加"()",则返回的是整个方法的字符串形式
        document.write("<br>");
        document.write(obj.func1());//若使用方法名加"()",返回的则是方法执行的结果
        obj.property5="我是在外部添加的属性";//一个对象可以在外部添加新属性,若新属性名称重复,则覆盖掉原属性值
        document.write("<br>");
        document.write(obj.property5);
        /*TIP:整个js文档可以看成是名为window的对象,文档里所有全局变量都是window的属性,所有函数都
        是window对象的方法,可以像普通对象调用属性和方法一样使用window调用全局变量和函数,只是一般情
        况下可省略*/
    </script>

     

  8. JavaScript中的函数:不同于Java中的万物皆对象理念,js中的函数可以单独存在并调用,下面是一个函数实例及其说明:
    <script>
        /*传统方式,定义一个函数需要使用关键字"function",一个函数包括函数名、参数、函数体、返回值共4部分。
        函数名用来调用函数;
        参数可以为0个或者多个,当实际调用时实参和形参个数不一致时,按照形参的数目,少的部分填充undefined,多的部分省略;
        函数体用来实现函数目的;
        返回值需要使用"return"关键字,一旦返回,直接跳出函数,return后面的语句均不会执行。
        若函数中未使用"retrun"返回,实际执行过程中也会返回一个undefined值*/
        function fun1(var1,var2){
            if(var1>var2)
                return var1;
            return var2;
        }
        /*在ES6新的更新中,增加了使用箭头"=>"定义函数的方式,此方式可以省略关键字"function",可以使定义函数变得更简洁;
        下面使用箭头定义的函数fun2功能与fun1完全一致。*/
        fun2=(var1,var2)=>{
            return var1>var2?var1:var2;
        }
        
    </script>

     

  9. JavaScript中的局部变量和全局变量:
    <script>
        //js中,可以使用var声明变量,再赋值,如下:
        var var1="我在函数外部,先声明后赋值,我是全局变量var1";
        //也可以不声明,直接赋值,如下:
        var2="我在函数外部,不声明直接赋值,我是全局变量var2";
        //以上两种在函数外部的变量均为全局变量,一旦产生,在js中任何地方都可以调用
        fun1=()=>{
            //函数内部通过var声明的变量均为局部变量,函数运行完成即销毁
            var var1="我在函数内部,先声明后赋值,我是局部变量var1";
            //函数内部直接赋值变量,一旦函数运行,即生成一个全局变量,函数不运行则不会生成
            var2="我在函数内部,不声明直接赋值,我是全局变量var2";
            /*在函数内部想调用外部同名全局变量,可以使用window.variable,可以把整个js文档看作window对象,
            则所有全局变量都是window对象的属性*/
            console.log(window.var1);//调用的是外部变量var1
            console.log(var1);//直接调用则是内部局部变量var1
        }
        fun1();//运行函数,生成全局变量var2
        console.log(var2);//值是函数内部定义的全局变量var2,因为同名变量会覆盖前者的值
        //-------------------------------------------------------------------------------------------
        //ES6中,新增关键字let和const,let用于创建局部变量,const用于创建不变量,下面详细说明let用法
        //由let声明的变量有效性局限于一个大括号内部
        {
            let i=10;
            console.log(i);//可正常显示
        }
        //console.log(i);//此时i已销毁,会发生"i" is not defined错误
        /*let在循环中的使用:一般我们使用for循环时,会定义一个mark数i,i递增到某一个数后跳出循环,在
        java中,此时i会被销毁,你无法使用它,但在js中,i会变成一个全局变量,你依然可以在后面的程序中
        使用它,若想要跳出循环即销毁mark数,可使用let声明变量*/
        for(let i=0;i<10;i++);
        //console.log(i);//此时i已销毁,会发生"i" is not defined错误
        for(var i=0;i<10;i++);
        console.log(i);//此时控制台显示i=10,可以正常显示
        for(let i=0;i<100;i++);
        console.log(i);//此时控制台显示i=10,说明由let声明的变量i只局限在循环内部,不影响全局变量i的值
        //网络上的一个例子
        for(let i=0;i<10;i++){
            let i="abc";
            console.log(i);//控制台显示10次"abc",这说明由let声明的变量甚至在循环部分和循环体内都是互不影响的两个变量
        }
        console.log(i);//i=10
    </script>

     

  10. JavaScript中的变量作用域:在拥有上下级关系的作用域中,下级作用域要寻找一个变量,总是先在自己的作用域中寻找,若无则在上级作用域中寻找,以此类推,直到全局作用域,若全局作用域也无此变量,则抛出变量未找到错误;一个作用域无法引用与其平行的作用域的变量。
  11. JavaScript中的事件:js中的代码除了可以在js文档或者<script></script>中运行,也可以与html文档中的元素事件相结合,结合方式的一般格式为<element event="js statement">,element是元素名,event是对应元素的某个事件,如页面已被加载完成(onload)、按钮被点击(onclick)、html元素改变(onchange)等,"js statement"可以是具体的js语句,也可以是js函数的引用,注意需要使用双引号或者单引号包括。例:<button οnclick="alert(Date())">,在按钮被点击后弹出时间提示;<input type="text" οnchange="alert("已改变")">,输入框内容改变时点击enter键会弹出“已改变”提示。
  12. 一个简单的HTML页面与JS动作相结合的实例:
    <body>
        <input type=button id=submit1 value="事件动作在元素处定义" onclick="func1()"><br><!--在元素处定义的事件动作可重复使用-->
        <input type=button id=submit2 value="事件动作在javascript中定义"><br>
        <input type="text" id="text" value="12333">
        <script>
            //---------------------------------------------------------------------------------------------------------------
            var var1=document.getElementById("submit1");//按钮1元素
            var var2=document.getElementById("submit2");//按钮2元素
            var var3=document.getElementById("text");//文本框元素
            var count=0;//全局变量计数
            //函数每运行一次,文本框内容会随着点击次数的改变而改变
            func1=()=>{
                count++;
                var3.value="第"+count+"次点击";
            }
            //函数运行会导致页面弹出如下内容的提示
            func2=()=>{
                alert("现在时间是:"+Date());
            }
            var2.onclick=func1();//以此种方式定义的事件动作只能在加载时运行一次,不能重复使用,区别于在元素处定义的动作
            var2.addEventListener("click",func1());//以此种方式注册的监听事件也只能在加载时运行一次,不能重复使用
            window.onload=func2();//注册window.onload属性(可省略"window"关键字),当页面加载完毕会运行func2()函数
        </script>
    </body>

     

  13. JavaScript字符串:JS中的字符串属性及其方法见如下网址:https://www.runoob.com/js/js-strings.html
  14. JavaScript运算符:JS中"+"运算符和java中基本一样,可以对数字做和运算产生新的数字,也可以对字符串做连接运算产生新的字符串,在数字+字符串情况下,会首先把数字转换成字符串,再做连接运算;特别的,如果有多个数字/字符串连加,总会判断最左侧两个运算因子类型,再决定是做和运算还是连接运算,最后产生的结果再和剩余因子做连加。
  15. JavaScript运算符:JS中有两种等于比较运算符,"=="和"===",前者只要求比较两端值相等,类似于java中的equals()函数;而后者要求比较两端的内存地址相同(从而值一定相同),类似于java中的"=="运算符。例:var1="123",var2=new String("123"),(var1==var2)=>true,(var1===var2)=>false。
  16. JavaScript运算符:关于JS中的三元运算condition?value1:value2,经实测(在js和java中均可),value2不仅可以是一个值,也可以是返回值相同的另一个三元运算,例:x==1?"x值是1":x==2?"x值是2":x==3?"x值是3":"x值不是1、2、3",以上实例判断x的值是不是1、2、3。
  17. JavaScript运算符:JS中的任何值都对应一个boolean值,具体来说,数字0,空字符串""null类型,undefined类型,NaN类型对应false,其他对应true。对任何做逻辑运算的变量,!var=(var=>false)?false:true,var1&&var2=(var1=>false)?var1:var2,var1||var2=(var1=>true)?var1:var2
  18. JavaScript中的break和continue:break用于跳出循环或者switch语句,continue只能用于循环语句,作用是跳过本次循环,进入下一次循环。js中可以为代码块(一般为大括号包括)设置标签(label),格式为labelname:{},break和标签结合使用可以跳出任何JS代码块,格式为break labelname,详情可见下述网址:https://www.runoob.com/js/js-break.html
  19. JavaScript中的null类型和undefined类型辨析:不同点null表示一个空对象引用;常用于赋值给某些不再使用的对象所对应的变量名,以解除它们的映射关系,释放内存;null可以视为0与数字相加,typeof(null)=objectundefined是任何未赋值的变量var的默认值;typeof(var)=undefined,typeof(undefined)=undefined;undefined不可与数字相加(返回NaN)。相同点:两者都是一类特殊的基本数据类型,都保存在栈中,两者都可与字符串相加,分别等于"null"/"undefined",两者都可赋值给一个变量,从而清空变量值。TIP(null==undefined)=>true,(null===nudefined)=>false
  20. JavaScript数据类型及类型转换:多且杂,参见:https://www.runoob.com/js/js-type-conversion.html
  21. 一个简单的日期格式化js程序以及prototype使用的一个实例:
    <script>
        /*prototype意为"原型",在JavaScript中指代一个原型对象,每种对象都有自己的原型对象(类似Java中的父类?),原型对象
        也有自己的原型对象,这样不断上溯,回到所有对象的顶端Object。这里的对象,包括对象(object)、函数(function)、数组(Array)
        等,既包含JS自带的函数如Date(),也包括用户自建的对象/函数/数组等
        利用prototype,我们可以给对象添加新的属性和方法,如下,我们给Date对象添加了新方法MyFormat()*/
        Date.prototype.MyFormat=function(ftm){
            var year="year",month="month",day="day",hour="hour",minute="minute",second="second";//固定关键字符串
            var datee={};
            datee[year]=this.getFullYear();//给Date对象添加方法,this即表示调用此方法的Date对象实例本身
            datee[month]=this.getMonth()+1;//获得月份,getMonth()方法月份从0月起,因此真实月份应该+1
            datee[day]=this.getDate();//getDate()方法获取月日期(1-31),getDay()方法获取周日期(0-6)
            datee[hour]=this.getHours();
            datee[minute]=this.getMinutes();
            datee[second]=this.getSeconds();
            ftm=String(ftm);
            for(var i in format_map){
                ftm=ftm.replace(format_map[i],datee[i]);
            }
            return ftm;
        }
        //格式化对象与日期属性的映射
        var format_map={
            year:"yyyy",//使用"yyyy"表示年份(4位数字)
            month:"MM",//使用"MM"表示月份,大写与分钟数区别开
            day:"dd",//使用"dd"表示日期
            hour:"hh",//使用"hh"表示时钟数
            minute:"mm",//使用"mm"表示分钟数
            second:"ss",//使用"ss"表示秒钟数
        }
        console.log(new Date().MyFormat("yyyy-MM-dd  hh:mm:ss"));//控制台显示2020-5-27  23:46:23
    </script>

     

  22. JavaScript正则表达式初步:
    <script>
        var str="abcdefghijklmnopqrstuvwxyz_1234567890||ABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890||abcdefghijklmnopqrstuvwxyz_1234567890";
        var length=str.length;//字符串的长度
        /*与java中不同,正则表达式作为一个类需要使用构造方法创建,JavaScript中正则表达式的创建简单许多,下述公式即创建正
        则表达式的一般方法:var regex=/表达式主体(regular expression)/修饰符(modifier)(可省略),注意正则表达式无需加引
        号,加引号即变为一般的字符串。正则表达式一般用于字符串的搜索(search()函数)和替换(replace()函数)*/
        var pattern=/_123/;//一个正则表达式,省略了修饰符,即表示为"_123"的字符串
        var n=str.search(pattern);//字符串的搜索函数返回匹配表达式子串首位下标,若无匹配则返回-1
        //console.log(n);//n=26
        var n1=str.search("_123");//对于简单的正则表达式,其等同于与表达式相同的字符串
        //console.log(n1);//n1=26
        var pattern1=/ABC/ig;//一个正则表达式,修饰符i(ignorecase)表示不区分大小写,修饰符g(global)表示全局匹配,即匹配所有满足的字串(默认只匹配第一个)
        var newstr=str.replace(pattern1,"我是替换文本");//字符串替换函数返回一个替换后的新字符串,原字符串不变
        //console.log(newstr);//newstr=我是替换文本def...||我是替换文本DEF...||我是替换文本def...
        //------------------------------------------------------------------------------------------------------------------
        //关于全局匹配字符串下的替换逻辑
        var str1="aaaaaaaaaaa";//定义一个长度为11的字符串a
        var pattern2=/aaaa/g;//定义一个长度为4的正则表达式a,模式为全局匹配
        var newstr1=str1.replace(pattern2,"bbbaa");//newstr1=bbbaabbbaaaaa
        /*由上可见:
        1、正则匹配不受替换文本的影响,只会在原字符串中寻找匹配子串;
        2、匹配成功后,再次匹配会从匹配到的子串末位+1开始,而不受已匹配过的前面的子串的影响*/
        //------------------------------------------------------------------------------------------------------------------
        //使用constructor创建正则表达式,一般为:var regex=new RegExp("regular expression","modifier"),其与上述创建方法完全等效
        var pattern3=new RegExp("ABC","ig");//等效于:pattern3=/ABC/ig
        var b=pattern3.test(str);//正则表达式方法test()用于测试一个字符串是否存在匹配表达式的子串,返回一个boolean值
        console.log(b);//b=true
        /*关于正则表达式方法RegExp.exec(str),搜索与表达式匹配的子串,若无则返回null,若有则返回一个结果数组,结果数组一般包含以下信息:
        0:匹配到的文本
        1:RegExp第一个分组最后匹配到的子串,如果有分组的话(正则表达式中一个小括号包括起来的部分称为一个分组,关于分组可详见22规则)
        2:RegExp第二个分组最后匹配到的子串,如果有第二个分组的话
        ...以此类推
        index:匹配文本首字母下标
        input:匹配的字符串
        length:指匹配到文本的个数,也即分组个数+1
        !!!特别注意:RegExp还有一个属性lastindex,此属性表示本次匹配到的子串末位下标+1,即下次运行匹配开始的位置,当设置modifier=
        g(global)时有效,此时exec会根据lastindex轮流匹配字符串中每一个符合的子串,当返回null时,lastindex恢复到0。
        注意1:test()函数也会影响lastindex数值
        注意2:即使中途匹配的字符串换掉,即input不同,lastindex也不会恢复到0,实际使用时注意这一点*/
        var array
        var pattern3=/(ABC)(de)/ig;//此正则表达式有两个分组,因此exec()执行后返回的结果有三个子串,分别对应整个表达式匹配的子串和两个分组最后匹配到的子串
        while((array=pattern3.exec(str))!=null){
            console.log(array[0]);//显示整个表达式匹配到的子串
            console.log(array[1]);//显示第一个分组(ABC)匹配到的子串
            console.log(array[2]);//显示第二个分组(de)匹配到的子串
            console.log(pattern3.lastIndex);//显示下次开始匹配的位置
        }
        /*上面循环运行结果:
        abcde   //匹配到的子串
        abc     //匹配到的子串
        de      //匹配到的子串
        5       //下次匹配开始位置下标
        ABCDE   //匹配到的子串
        ABC     //匹配到的子串
        DE      //匹配到的子串
        44      //下次匹配开始位置下标
        abcde   //匹配到的子串
        abc     //匹配到的子串
        de      //匹配到的子串
        83      //下次匹配开始位置下标*/
    </script>

     

  23. JavaScript正则表达式规则:
    <script>
        /*JavaScript中的正则表达式--->修饰符(modifier)有三个:
        i:ignoreCase,表示匹配不区分大小写
        g:global,表示全局匹配,不加则匹配到第一个满足条件的即停止匹配
        m:multiline,表示执行多行匹配,在使用"^"和"$"匹配开头和结尾时,多行匹配模式匹配每一行的开头和结尾,默认只匹配整个文本的开头和结尾*/
        //---------------------------------------------------------------------------------------------------------------------------
        /*JavaScript中的正则表达式--->方括号("[]")的使用:
        方括号("[]")一般用来查找在某一个范围内的一个字符,这里的字符可以是英文大小写字母,也可以是0-9的数字,还可以是其他ASCII码字符(?);
        用方括号表示字符范围一般有以下几种方式,以下"a1","a2","a3"表示任意一个字符
        [a1a2a3]:这种写法表示或者a1,或者a2,或者a3的一个字符
        [a1-a2]:这种写法表示从a1至a2的ASCII码之间的任一字符,包括a1和a2;如[0-9]表示从0-9的数字,[a-z]表示从a-z的小写字母
        [a1-a2|a2a3]:这种写法是[a1-a2]和[a2a3]所规定范围的并集,中间用"|"隔开,可以有多个合写
        [^a1a2a3]、[^a1-a2]、[^a1a2|a1a3|a2a3]:中括号内字符前面加上"^",表示匹配字符/字符串范围取反
        !!!注意,[]总是只匹配一个字符*/
        //---------------------------------------------------------------------------------------------------------------------------
        /*JavaScript中的正则表达式:--->元字符:
        元字符是具有特定含义的字符,以下为常见元字符及其解释
        .:"."匹配任意一个字符,除了换行符和行结束符,等价于[^];
        \w:匹配一个单词字符(word),注意"w"为小写所谓单词字符,包括0-9,a-z,A-Z,_,即数字字符,英文大小写字母和下划线;
        \W:匹配一个非单词字符,注意"W"为大写,即\w取反;
        \d:匹配一个数字字符(decimal),即0-9;
        \D:匹配一个非数字字符,即\d取反;
        \s:匹配一个空白字符(space),包括空格符(space),制表符(tab),回车符(carriage return),换行符(new line),垂直换行符(vertical tab),换页符(form feed);
        \S:匹配一个非空白字符,即\s取反;
        \b:匹配单词边界(border),/\bregexp/即表示匹配以regexp开头,/regexp\b/即表示匹配以regexp为结尾,注意匹配的是regexp,而不是单词;
        \B:匹配非单词边界,与\b意义相反,匹配不以某个样式开头或者结尾的单词;
        \0:匹配一个null字符;
        \n:匹配一个换行符(new line);
        \f:匹配一个换页符(form feed);
        \r:匹配一个回车符(return);
        \t:匹配一个制表符(tab);
        \v:匹配一个垂直制表符(vertical tab);
        \xxx:匹配以八进制数xxx(必须写三位,不到三位则填充0)规定的一个字符;
        \xdd:匹配以十六进制数dd(x是字符"x",不是具体数字,dd是一个两位数字)规定的一个字符;
        \uxxxx:匹配以十六进制数xxxx(u是字符"u",不是具体数字,xxxx是一个四位十六进制数)规定的一个Unicode字符;
        !!! 上面最后三位即以ASCII码表示一个字符,与[]结合即可用数字表示某一区间ASCII码对应的字符,例[\x00-\xff]表示0-256的全部ASCII对应字符*/
        /*关于单词边界\b和非单词边界\B:其他元字符很好理解,总是匹配一个字符串中的某个字符,(非)单词边界匹配的不是字符,
        而是字符之间的边界(空隙),\b匹配的是一个单词的第一个字符前面的位置或最后一个字符的后面的位置,\B匹配的是单词中间
        的各个字符之间的位置,下面用例说明*/
        var str="I like playing game";//一个字符串,四个单词
        var patt=/\b/g;//正则表达式,全局匹配单词边界
        var newstr=str.replace(patt,"*");//newstr=*I* *like* *playing* *game*,即把单词边界都替换成'*';
        patt=/\B/g;//全局匹配非单词边界
        newstr=str.replace(patt,"*");//newstr=I l*i*k*e p*l*a*y*i*n*g g*a*m*e,即把非边界都替换成'*';
        patt=/\b(?=\w)/g;//利用正则前瞻,可以匹配出所有单词的前边界
        newstr=str.replace(patt,"*");//newstr=*I *like *playing *game
        patt=/\b(?!\w)/g;//利用正则负前瞻,可以匹配出所有单词的后边界
        newstr=str.replace(patt,"*");//newstr=I* like* playing* game*
        //console.log(newstr);
        /*一个有意思的例子,当数字过大时,我们可以使用千分位来表示数,以便读数,例:11111111111111=>11,111,111,111,111;
        我们可以利用正则表达式方便的将一个数字转换为千分位表达法:*/
        var num="11111111111111111111111111";
        //匹配数字中的这些非边界空隙(\B),其前文(利用前瞻)总是有至少1组3位数字((\d{3})+),且除了3位1组的数字,没有其他数字
        var patt=/\B(?=(\d{3})+(?!\d))/g;
        var newnum=num.replace(patt,",");//newnum=11,111,111,111,111,111,111,111,111
        //console.log(newnum); 
        //---------------------------------------------------------------------------------------------------------------------------
        /*JavaScript中的正则表达式:--->量词:
        正则表达式不仅可以定义匹配模板,还可以对模板进行量词上的限制,一般表示量词使用的符号有0-9(数字),{}(大括号),+,*,?,下面详细说明:
        (regexp)+:表示至少匹配一个regexp,如果regexp为一个字符,可以省略小括号,下同;
        (regexp)*:表示匹配0个或多个regexp;
        (regexp)?:表示匹配0个或者1个regexp;
        (regexp){X}:表示通用匹配个数的可以使用大括号,(regexp){X}表示匹配X个regexp;
        (regexp){X,Y}:表示匹配至少X,至多Y个regexp,当无下限时可省略X,当无上限时可省略Y,中间的","不能省略,否则只表示匹配确定的个数;*/
        //---------------------------------------------------------------------------------------------------------------------------
        /*JavaScript中的正则表达式:--->零宽断言:
        正则表达式不仅可以匹配某一模式的字符串,还可以要求其上下文匹配某种模式,上下文不占据匹配字符串的长度(只作为匹配条件),因此这种表达式
        叫做零宽断言
        ^(regexp):表示匹配以regexp为开头的字符串,注意区别元字符\b,\b匹配的是单词(一般以空白字符分割),^匹配的时字符串(包含空白字符);
        (regexp)$:表示匹配以regexp为结尾的字符串,注意区别元字符\b;
        (regexp)(?=regexp1):表示匹配regexp字符串,且其下文模式为regexp1,这种匹配模式也叫做“前瞻”;
        (regexp)(?!regexp1):表示匹配regexp字符串,且其下文模式不是regexp1,与上面的恰恰相反,这种匹配模式叫做“负前瞻”;
        (?<=regexp1)(regexp):与“前瞻”相对应的,还有“后顾”,表示其上文模式必须是regexp1,此种模式似乎在js中不支持;
        (?<!regexp1)(regexp):与“负前瞻”相对应,还有“负后顾”,表示其上文模式必须不是regexp1,此种模式在js中也不支持;*/
        //---------------------------------------------------------------------------------------------------------------------------
        /*JavaScript中的正则表达式:--->分组及其引用:
        分组:正则表达式使用小括号"()"分组,表示括号内的模式按照一个整体匹配,一般与量词结合使用;
        向后引用:分组的正则表达式还可以使用"\n"来引用前面匹配到的文本,其中n是个数字,表示第n个分组,详情可见下例说明;
        子模式匹配:我们可以在正则表达式外使用"$n"来引用正则表达式第n个分组所匹配到的文本,注意\n使用于正则表达式内部,即参与表达式匹配,而
            $n用于表达式外部,常用于replace()函数中,以示区别;两者相同点在于都是引用已匹配到的文本而非直接引用模式。
        非捕获分组(?:):默认分组都是捕获性分组,可以参与引用及其位置计数,一个分组不可引用及位置计数,即为非捕获分组;想要一个分组是非捕获
            分组,只需在其括号内部最前面加上"?:"即可,类如(?:regexp)即是一个非捕获分组*/
        var str="123456123789";
        var p1=/(\d+?)(.+)\1/g;
        var re=p1.exec(str);//re=1234561,\d+?使用非贪婪模式,匹配到的文本是"1",\1引用第一个分组(\d+?)匹配到的文本"1",所以匹配到1234561;
        var str="123=321"
        var p1=/(\d+)=(\d+)/g;
        var re=str.replace(p1,"$2<>$1");/*re=321<>123,p1匹配文本是"123=321",其中第一个分组(\d+)匹配到的文本是"123",第二个分组(\d+)匹配
            到的文本是"321",所有$1=123,$2=321,所以替换文本"$2<>$1"等价于"321<>123";*/
        //---------------------------------------------------------------------------------------------------------------------------
        /*正则表达式其他重要注意事项:
        !!! 关于()(小括号):在正则表达式中小括号是特殊字符,表示分组,不能直接匹配,(regexp)表示regexp是作为一个整体来匹配的;
        !!! 关于|(分隔符):在正则表达式中分隔符也是特殊字符,表示或,不能直接匹配,(reg1)|(reg2)|(reg3)表示匹配reg1或者reg2或者reg3;
        !!! 正则表达式中的特殊字符:由上面可知在正则表达式中有许多字符拥有特殊含义,不能直接匹配,如'\'、'.'、'|'、'{}'、'[]'、'()'、
            '?'、'*'、'+'等,要匹配这些字符,需在前面加上转义字符'\',即\specialmetachar表示匹配specialmetachar;
        !!! 正则表达式中的贪婪模式与非贪婪模式:贪婪模式算法是尽可能多的匹配到符合表达式的子串,一直到匹配失败;而非贪婪模式则会根据最小匹配
            规则去匹配子串,让子串尽可能的短,正则表达式中的量词默认贪婪模式,若要取消贪婪模式,只需在量词后面加上一个'?';例子如下:*/
        var str="aaaaaaaa";
        var patt1=/a{2,5}/g;
        var patt2=/a{2,5}?/g;
        var re1=patt1.exec(str)[0];//re1=aaaaa
        var re2=patt2.exec(str)[0];//re2=aa
    </script>

     

  24. JavaScript详解:https://www.cnblogs.com/mq0036/p/6013225.html
  25. JavaScript中的异常处理:
    <body>
        <input type=text id="text">
        <button onclick="exception_function()">点击弹出错误</button><br>
        <p id="p"></p>
        <script>
            //js中的异常处理类似于java,try语句负责运行可能错误的代码;catch语句负责捕获并处理错误;finally中的语句一定会执行,可省略。
            //例:下面的例子中故意写错函数名,js引擎会抛出错误
            try{
                allert("welcome!");//故意写错函数名称
            }catch(err){
                console.log(err.message);//error.message获得错误信息,控制台抛出错误"'allert' is not defined"
            }finally{
                document.write("无论有无错误,我一定会执行");//web页面显示"无论有无错误,我一定会执行"
            }
            //-------------------------------------------------------------------------------------------------------------------
            //js中不仅可以抛出函数内置错误,还可以使用throw关键字自定义错误,错误可以是JavaScript中的字符串、数字、逻辑值或者对象
            exception_function=()=>{
                var value=document.getElementById("text").value;
                var p=document.getElementById("p");
                try{
                    if(value=="") throw "值为空";
                    if(/\s+/g.test(value)) throw "值中包含空格";
                    if(isNaN(value)) throw "值非数字";
                    value=Number(value);//当遇到异常时会跳出try语句,因此只有当输入值时非空且为数字时会执行此语句
                    if(value>10) throw "数字过大";
                    if(value <0) throw "数字过小";
                    alert("congratulation!!,你输入的值是:"+value+",符合要求");
                    p.innerHTML="";
                }catch(err1){
                    p.innerHTML="值是:"+value+";错误是:"+err1;
                    document.getElementById("text").value="";//输入框设置为空
                }
            }
        </script>
    </body>

     

  26. JavaScript中的变量提升机制:在JS中,有一个预解析过程,在这个过程中,会发生变量提升,即遍历整个js文档,查找其中所有全局变量的声明,将其提升到文档最前方(注意变量只提升其声明,赋值不提升,按顺序运行);除了变量提升,按照一般模式定义的函数(类如function fname(){})也提升到最前方(函数提升包括其函数体,即整个函数都提升到最前方,且优先级高于变量);由于变量提升机制,我们使用变量和函数时可以先赋值(变量),后使用,再声明;也由于这个机制,变量的值一定会覆盖同名函数,导致函数无效;需要注意的是,当函数采用var=function(){}方式定义时,此时var看作一般变量而非函数变量。关于变量提升机制详细说明:https://www.runoob.com/js/js-hoisting.html,下面几篇笔记读完很有益处。
  27. JavaScript用于验证html表单:
    <html>
    <head>
    <meta charset=utf-8>
    <title>html表单-发送页</title>
    <!--对一类元素设置格式-->
    <style>
    .test{
    	width:500px;
    	background-color:gray;
    	color:yellow;
    	text-align:left;
    	margin-bottom:20px}
    .test1{
    	text-align:center}
    h3{	
    	width:500px;
    	text-align:center}
    </style>
    <script>
    	function check(){
    		var value1=document.getElementById("name").value;
    		var value2;
    		for(var ele of document.getElementsByName("gender"))//for/in用于循环一个对象的属性,for/of可用来循环一个数组/列表/集合/字符串的内容
    			if(ele.checked)
    				value2=ele.value;
    		//var value2=$('input[name="gender"]:checked').val();//jQuery方法,浏览器不支持
    		//console.log(value2);
    		var value3=document.getElementById("age").value;
    		//alert(value1+"-----"+value2+"-----"+value3);
    		if(value1==""||value1=="your name"){
    			alert("请正确填写您的姓名");
    			return false;
    		}
    		if(value2==undefined){
    			alert("请选择您的性别");
    			return false;
    		}
    		if(isNaN(value3)||value3==""){
    			alert("请正确填写您的年龄");
    			return false;
    		}
    	}
    </script>
    </head>
    <body>
    <form class=test action=11_表单-接收页.html onsubmit="return check()"><!--onsubmit属性用来决定是否提交表单-->
    请输入名称&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:
    	<input type="text" name="name" value="your name" id="name"><br>
    请选择性别&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:
    	<input type=radio value=male name=gender>男
    	<input type=radio value=female name=gender>女<br>
    请输入您的年龄:
    	<input type="text" value="your age" name="age" id="age"><br>
    <input type="submit" value="点击提交">
    <!--<button onclick="check()">点击提交1</button>
    <button onclick="check()">点击提交2</button>-->
    </form>
    <a href=11_表单-接收页.html target=_blank>打开表单-接收页</a>
    </body>
    </html>

     

  28. JavaScript文本获取本页地址相关:
    <script>
        console.log(window.location.pathname);//获取文件地址
        console.log(window.location.href);//获取完整网址
        console.log(window.location.port);//获取关口
        console.log(window.location.protocol);//获取url协议
        console.log(window.location.hash);//获取url中#后面的部分(页内地址)
        console.log(window.location.host);//获取主机
        console.log(window.location.hostname);//获取主机名称
        console.log(window.location.search);//获取url中?后面的部分(包括?)
    </script>

     

  29. JavaScript中的闭包:
    <script>
        /*js中的函数闭包:*/
        var out;//外部全局变量
        var a=(function(){
            var x=0;
            return function(){
                return x+=1;
            }
        })();
        /*外层函数自运行后,初始化私有变量x,并将匿名函数function(){return x++}赋值给a,此时a是一个函数变量;外层函数运行完后,一般情况下,
        其私有变量x会被垃圾回收,不可用,但由于函数变量a指向的函数中仍然有指向x的指针,所有x不会被垃圾回收处理掉,但由于其私有变量属性(位
        于函数内部作用域),在函数外部除了变量a,没有任何其他方法改变x的值,这样就得到一个可控且安全的变量。"直观的说就行形成一个不销毁的栈
        环境"*/
        out=a();//函数变量a后面带括号即为运行a所指向的函数,返回x自增的值,并将此值赋值给全局变量out
        console.log(out);//out=1
        out=a();//a()再次运行,x的值再次自增
        console.log(out);//out=2
        out=a();//a()再次运行,x的值再次自增
        console.log(out);//out=3
        out=0;//注意out所赋之值只是变量a所指函数的返回值,是一个存粹的数量,所有out值的改变不会影响闭包内变量x的值,此处令out=0;
        console.log(a());//此时a()返回值是4,不受out影响
        //以上为闭包内变量是基本类型情况下,若闭包内变量是一个对象,则外部赋值后可通过外部变量改变
        var b=(function(){
            var y={"name":"jobs","age":18,"nationality":"USA"};
            return function(){
                return y;
            }
        })();
        out=b();//此时out值即为闭包内的值y;
        console.log(out);//out={age: 18, name: "jobs", nationality: "USA"}
        out.age=19;//可通过out改变闭包内的值
        out.gender="male";
        console.log(b());//此时通过运行闭包函数返回的变量已经变成了{age: 19, gender: "male", name: "jobs", nationality: "USA"}
        out="new value";//但如果out为重新赋值,则不会影响闭包变量
        console.log(b());//此时闭包变量仍然是{age: 19, gender: "male", name: "jobs", nationality: "USA"}
        /*形成以上情况的原因在于JS中的变量内存分配机制:对于基本类型变量,没有属性和方法,其存于栈内存中,变量名直接指向其值;所以变
        量名改变数值只是在栈内存中重新开辟一个variablename:value空间,并不会影响原来的值;对于引用类型变量,栈内存中存放的是变量名和
        变量本身的内存地址,即variablename:location,变量本身存于堆内存中,一旦将其赋给其他变量名variablename2,那么variablename2也就
        获得了变量本身的地址,自然可以通过变量的方法改变自身,但重新赋值则意味着variablename2对应的location改变,这不会影响变量本身。
        所以形成有效函数闭包(安全可控)三要素是:
            自由变量:位于函数作用域之外的变量,一个函数总是能调用其上层作用域的变量,此变量相对于函数称为自由变量;如果此变量不是全局
                    变量,则其会在变量所在作用域运行完成后销毁;
            函数变量:函数可以赋值给一个变量,且通过变量可以运行函数;有了变量指向函数,则函数及其内部所涉及的变量均不会被拉回回收处理
                    掉,函数可以通过变量运行,则我们可以通过变量控制自由变量的值;
            栈内存:自由变量必须位于栈内存中,否则通过外部赋值可以轻松改变变量的值,此变量也就不具有安全性;*/
    </script>

     

  30. JavaScript中的闭包:
    <script>
        /*关于JavaScript中闭包的进一步想法:js中的闭包本质是提供一个安全使用变量的方法;相较于其他完善的面向对象语言(如java),
        js中没有private、protected等修饰词,如果我们只是把变量定义在一般的对象中(甚至定义成全局变量),那么我们可以通过这个对象
        实例随意的改变变量的值,这就不是一个安全的变量。例如下*/
        var obj={
            x:0,//对象中的变量,一个数值
            add:function(){//对象中的方法,按照特定方式改变变量的值
                this.x++;
            },
            subtract:function(){//对象中的方法,按照特定方式改变变量的值
                this.x--;
            }
        }
        console.log(obj.x);//x的初始值为0
        obj.add();//通过调用方法,以特定方式改变x的值
        console.log(obj.x);//x=1
        obj.x=10;//但我们可以直接通过赋值的方式改变x的值,此时x就显得不是那么安全
        console.log(obj.x);//x=10
        console.log("--------------------------------------------------------------------------------------------------")
        /*函数作为一类特殊的对象类型,其特殊之处在于既有对象的特性,可以拥有属性和方法;又拥有自己的词法作用域,一旦函数运行完毕,
        定义于自己内部的局部变量无法通过外部访问,保证了安全性。在JS闭包介绍中,我们可以通过return语句将函数中的闭包函数赋值给外
        部变量,从而可以获得和操控一个安全的变量,在下面,我们演示另一种方法获得一个函数闭包*/
        function func1(value){
            var y=value;//函数中的局部变量,注意y没有使用this修饰,所以func1()函数初始化的时候,y不会指向任何对象
            /*我们想让y每次该改变增加10,于是创建add()函数,注意add()函数创建时使用this修饰,这导致func1()函数初始化时,add()函
            数会成为一个对象的方法,即指向此对象*/
            this.add=function(){
                return y+=10;
            }
        }
        func1(10);//直接运行函数,则此函数视作全局变量的函数,里面的this指向window,y初始化=10
        console.log(window.y);//显示undefined,这说明外部无法访问函数内部局部变量y
        console.log(window.add());//可利用window运行add()函数改变y的值,此时y=20,实际上可省略window关键字
        var z=func1(20);//z即为函数func1()的返回值,func1()没有return语句,默认返回值是undefined
        console.log(z);//z=undefined
        var x=new func1(5);//通过new关键字初始化一个函数,实际是创建一个对象x,函数内this指向x,所有x拥有一个函数add()
        console.log(x.y);//显示undefined,这说明x无法直接访问(和改变)变量y
        console.log(x.add());//x可以调用add()函数改变y的值,注意此时y=15,和window中的y不一致,两个函数对象在内存中的不同位置,互不影响;
        /*以上通过1、创建一个函数;2、内部定义一局部变量;3、创建改变局部变量的内函数,一定要用this修饰;4、通过函数初始化将内函数赋值给某
        一对象,从而使得局部变量不可访问,只能通过对象调用内函数改变局部变量。这样就创建了一个js闭包*/
    </script>

     

  31. JavaScript中的this关键字:
    <script>
        /*JavaScript中的this关键字在函数和对象中的表现:由于js的弱类型,this关键字指向很复杂。
        在一般的面向对象语言中,this指代当前对象的一个引用,即指代调用包含此this关键字的属性、方法、类的一个对象实例。
        但在JS中,this关键字指代不是固定不变的,它会随着执行环境的改变而改变,一般总结如下:*/
        //1、在对象方法中,this指代调用此方法的对象实例
        var obj1={name:"jobs",age:18,gender:"male",add:function(){this.age+=1;}};
        obj1.add();//obj1调用add()方法,此时add()方法中的this即指代obj1这个对象实例,所以this.age=obj1.age
        console.log(obj1.age);//age=19
        console.log("--------------------------------------------------------------------------")
        //2、如果函数是单独的函数(也即是全局对象window的函数),此时this表示全局对象
        var gvar1=0;//一个全局变量
        function func1(){
            var gvar1=10;//函数局部变量,为了体现区别也命名为gvar1
            return this.gvar1;//返回函数外部全局变量,等价于window.gvar1
        }
        console.log(func1());//返回值为0,即返回的是全局变量
        console.log("--------------------------------------------------------------------------")
        //3、使用匿名函数效果同2,函数内部this同样指向全局变量
        var x=function(v){
            var a1=v;//正常声明变量,此时变量a1只是函数中的一个局部变量
            this.a2=2*v;//通过this声明变量a2,相当于定义了一个全局变量
            this.add=function(){return a1+=1};//通过this定义函数add,也是全局变量的函数
            console.log(this);//在函数内部打印this,会显示出window对象,即全局变量
        };
        x(10);//运行函数。只有运行函数,函数内部程序才会执行,否则相当于没有这段程序
        //console.log(a1)//发生错误,显示'a1' is not defined,外部无法访问函数内部作用域的局部变量
        console.log(a2)//正常运行,a2=20,说明a2确是全局变量,注意这种情况x不能调用a2(也不能调用a1)
        console.log(add())//显示a1=11,这说明,add()确为全局变量,且可以改变函数作用域内局部变量a1的值
        console.log("--------------------------------------------------------------------------")
        //4、通过new关键字构造函数,new func(var...)语句实际上是在内存中生成一个对象,此时函数内部this即指向这个对象
        var y=new x(1);//我们利用3中的函数通过new关键字新建一个对象
        console.log(y);//通过控制台显示,我们发现新对象y拥有一个属性a2和一个函数add,这说明在构造函数过程中,this指向y这个对象
        console.log(y.a1);//显示undefined,说明不能通过y访问函数局部变量a1
        console.log(y.add());//显示a1=2,这说明我们通过对象y的函数add()可以操控不可访问的局部变量a1的值,利用这一特性,我们可以构造闭包
        /*!!!   注意,通过y的add()函数调用的a1和3中全局变量函数add()调用的a1不同,这说明两者是在内存中的不同位置,除了结构相同外,
                两者所指向的对象不同,也互相不能影响,类似于java中一个类的不同实例
            !!!   以上1、2、3、4情况其实是统一的,即函数内this总是指向其所属的对象;要么属于全局对象,要么属于普通对象*/
        console.log("--------------------------------------------------------------------------")
        /*!!! 注意在对象中,无论其属于全局对象还是属于另一个对象,在其中使用this总是指代全局对象,这也是函数和对象的区别,
        例如下:*/
        var var1=10;//一个全局变量
        var obj2={
                var1:20,//为了体现区别,与全局变量同名
                var2:this.var1,//在obj2中使用this调用变量
                obj3:{var1:30,//为了体现区别,与全局变量同名
                        var2:this.var1//在obj3中使用this调用变量
                    }
                }
        console.log(obj2.var2);//显示10,即调用的是对象外的全局变量var1
        console.log(obj2.obj3.var2);//显示10,即调用的是对象外的全局变量var1
    </script>

     

  32. 其他
  33. 其他
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值