原生js基础课程

/* 
 * Version 1.0
 * Time 2018/3/13
 * Author parchments
 * Learn for duyijiaoyu
*/


js命名空间


作用: 管理变量, 防止污染全局变量, 适用于模块化开发

1、管理变量


/*
    var org = {
        part1: {
            lin: {
                name: "abc",
                age: 18
            },
            jing: {
                name: "jingjing",
                age: 19
            }
        },
        part2: {
            lin2: {
                name: "abc",
                age: 18
            },
            jing2: {
                name: "jingjing",
                age: 19
            }
        }
    }
    var parchments = org.part1.linjian,
        jing = org.part1.jing;
    console.log(jing.name);
    console.log(jing['name']);//建议这样访问属性
*/
    


2、闭包实现私有化,不污染全局变量


/*
    var name = 'abcd';
    var init = (function(){
        var name = 'abc';
        function callName(){
            console.log(name);
        }
        return function(){
            callName();
        }
    }());
    init();
    //结果是打印出abc,因为产生了闭包,函数被保存到了外部执行,拿的是init的AO,也因此没有污染全局的变量name,达到变量私有化的效果,init方法最后返回函数,执行callName();
    
    var initNew = (function(){
        var name = 123;
        function callName(){
            console.log(name);
        }
        return function(){
            callName();
        }
    }());
    initNew();
    //结果是打印出123,因为产生了闭包,函数被保存到了外部执行,拿的是init的AO,也因此没有污染全局的变量name,达到变量私有化的效果,init方法最后返回函数,执行callName();
*/


js实现链式调用(模仿jq)


//例如: lin.smoke().drink().smoke().perm();
/*    
    var lin = {
        smoke: function(){
            console.log("抽烟了");
            return this;
        },
        drink: function(){
            console.log("喝酒了");
            return this;
        },
        perm: function(){
            console.log("烫头了");
            return this;
        }
    }
    lin.smoke().drink().perm();
    //打印出 -->抽烟了  喝酒了  烫头了
*/

 

js属性表示方法


/*
    //obj.prop 内部隐式会转化成 obj['prop']去访问属性,所以用" . "访问属性的时候用obj['prop']的形式会更快
    //obj['prop']的形式更快而且更灵活,因为后面可以字符串拼接属性名,例如obj['prop' + num]
    //例如:
    var lin = {
        boke1: {name: "开源博客"},
        boke2:{name: "其他博客"},
        bokeFn: function(num){
            return this['boke' + num];
        }
    }
    
    //访问lin.bokeFn(1) -->打印出开源博客
    //访问lin.bokeFn(2) -->打印出其他博客
*/

 

js对象枚举


//遍历 枚举 enumeration


    1、遍历数组 --> for循环


        /*
            var arr = [1,2,3,4,5];
            for(var i = 0; i<arr.length; i++){
                console.log(i);
            }
            //打印出1 2 3 4 5
        */
        


    2、遍历对象 --> for in 循环


        /*
            var lin = {
                name : 'lin',
                age : 18,
                //prop : 1
            }
            for(var prop in lin){
                console.log(prop + " " + typeof(prop));
            }
            //for in 循环能实现对对象的遍历,把对象里面的每个属性名提取出来,有多少个属性名就会循环多少圈,目的只有一个就是遍历对象,单独给对象设立一个循环;通过对象属性的个数来控制循环的圈数,在循环每一圈时,会把对象的属性名放到prop里面。就相当于var 一个prop到lin,在每一圈的时候,prop相当于一个变量,每一圈的时候代替的属性名都不一样。其中prop是可自己设置的,但是lin一定是对象名
        
            //特别注意
            //如果要访问对象prop的属性名,一定要用[],否则,如果lin对象里面本来就有prop的属性,那访问的就不是对象的每个属性了,因为用了[prop],prop还是变量而不是定量
            for(var prop in lin){
                console.log(lin[prop]);//而不是console.log(lin.prop);
            }
        */
        


    2、hasOwnProperty过滤原型的属性


        /*
            //其中如果对象中有原型__proto__,再使用for in循环的话就会连原型上面的属性也取到,但是一旦原型链延展到Object.prototype上了,它就不会打印了,除非自己设置了Object.prototype = "XXX",否则是不会打印系统定义的东西
            //因此诞生出hasOwnProperty,和for in循环搭配使用,达到过滤原型上的属性,就只打印自己的属性
            
            var lin = {
                name : 'lin',
                age : 18,
                __proto__ : {
                    lastName : 'linlin'
                }
            }
            for(var prop in lin){
                //console.log(prop);            //如果只有这一句,没有用hasOwnProperty去限制或者过滤,那么会打印到原型上的属性
                if(lin.hasOwnProperty(prop)){    //其中,hasOwnProperty()是一个方法,带参数,就是prop,  -->会返回一个布尔值
                    console.log(prop);
                }
            }
            //因为一般遍历属性都是想要拿自己的属性而不是原型上的属性
        */

 

    3、in操作符


        /*
            //A、和hasOwnProperty()方法差不多,也是看这个属性到底是不是这个对象的
            //例如:
            var lin = {
                name : 123
            }
            //作用:判断name是不是lin对象的
            //'name' in lin -->会返回一个布尔值,其中name一定要用 双引号''
            //因为这样name是一个变量!!!
            //in会把是你的属性算是你的属性,也会把原型上的属性也算作是你的属性,所以出现的概率较低
        */

 

JS正则表达式

 

补充知识:

1、转义字符“  \ ”,反斜杠,会把反斜杠后面那个东西强制变成,转义符号不会输出,消除转义符号:“ \\ ”,把后面的转义符号转义掉

var str = "ab\"cd"

输出:(2行)

ab

cd

var str = "ab\\cd"

输出:abcd

2、\n,就是换行,在console.log()中查看

var str = "ab\ncd"

window中底层一个回车就是一个"\r\n"

var str = "ab\ncd"

输出:(2行)

ab

cd

3、\t 相当于一个tab键,制表符

var str = "ab\tcd"

4、在编程中让字符串换行

例如1:document.body.innerHTML = "<div><span></span></div>"

会把后面文本的形式的回车转义掉,变成不再是回车

例如2:document.body.innerHTML = "\

                                                   <div>\

                           <span></span>\                                                                        </div>\

"

例如3:通过字符串连接的方法,比较low

var text = 

    " <div>" + 

       " <span></span>" + 

   " </div>"

 

RegExp

正则作用:用户输入后判断字符串里面有没有特定片段、能被什么截取的、符合什么样的格式,甚至修改字符串的功能,正则一行就能处理

正则表达式是一个规则对象,对象里面包含的是规则,所以正则表达式也要创建出来

两个方法:

正则的方法:reg.test();只能判断字符串 有没有符合要求的片段,返回结果只有true或者false

字符串的方法:str.match();(g属性);可以把所有符合的东西匹配返回出来的,比true和false更直观点,还能告诉你多少个

 

两种创建方式:

1、直接量(推荐)

var reg = //;斜线中间些内容

var reg = /abc/,这代表我要匹配的规则是abc

var str = "abcd"   返回true  包不包含片段,区分大小写

var str = "abce"   返回false

使用方法:控制台:reg.test(str)

加属性(i)忽略大小写,i是ignoreCase的缩写

var reg = /abc/,不忽略大小写

var str = "abC"   返回false

var reg = /abc/i;

var str = "abC"   返回true

 

加属性(g),全局

var reg = /ab/g

var str = “abababab”

控制台:

str.match(reg);

利用reg的方法test已经不够了,所用str的字符串方法match,把正则表达式传进去就会把符合的片段挑出来;

如果reg后面的没有加属性g

打印的就是["ab"]

如果reg后面的加了属性g,就会把符合要求的片段全部拿出来

打印的就是["ab","ab","ab"]

 

加属性(m),执行多行匹配-----重要

var reg = /^a/g            " ^ "(尖号)        代表字符串开头

var reg1 = /^a/gm            " ^ "(尖号)        代表字符串开头

var str = “abcde\na”字符串换行变成多行字符串

在可控制台:

str.match(reg)---->打印出一个a["a"]

str.match(reg1)---->打印出2个a["a","a"]

 

2、new RegExp()

var str = "abcd";

var reg = new RegExp("abc");

var reg = new RegExp("abc",“i/g/m”);可以加属性

 

特殊的地方:

var reg = /abcd/i

var reg1  = new RegExp(reg);

现在reg和reg1打印出的值是一样,但他们是不一样的!!!

在控制台打印:

reg

返回:/abcd/i

reg1

返回:/abcd/i

reg.abc = 123;

reg1.abc

返回undefined

reg和reg1打印的样子一样,但是却不一样的。

如果去掉new,那就是一样的人,只是引用不同,2人拿着一个钥匙指向同一个房间。

var reg = /abcd/i

var reg1  =  RegExp(reg);

 

3、正则表达式规则

3.1方括号

1、[ ],一个[ ]代表一位,三个[ ]代表3个值,里面填的东西就是可取值的范围

var str = “1235890asdasd123”

var reg = /123/g

现在要:匹配字符串中有没有是这样的数字,即三个数字相连,要三个数字都是可变的,那现在就是[ ]代表一位。三个[ ]代表3个值

匹配三个数字相连

var reg = /[123456890][123456890][123456890]/g

匹配了就不会往回匹配;

var reg = /[ab][cd][d]/g        匹配第一个为a或者b,第二个为c或者d,第三个是d的全局

var str = “abcd”

在控制台输入str.match(reg)---->返回bcd

 

\cx 匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。

 

特殊字符

$ 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 \$。
( ) 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。
* 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。
+ 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。
. 匹配除换行符 \n之外的任何单字符。要匹配 .,请使用 \。
[ 标记一个中括号表达式的开始。要匹配 [,请使用 \[。
? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。
\ 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\",而 '\(' 则匹配 "("。
^ 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^。
{ 标记限定符表达式的开始。要匹配 {,请使用 \{。
| 指明两项之间的一个选择。要匹配 |,请使用 \|。

unicode(可以有在线转的)

一个编码对应一个字符,能代表很多语言

表达形式一定加\u;例如: \u0000  十六进制的四位数,简单的Unicode编码,基本能包含汉字

unicode编码包含了一切字符如:\u0000-\uffff

 

能代表一切的集合的 [\s\S]或者 [\d\D]

.的作用。

 

量词

\\n+     {1,}    1到正无穷

\\n*     {0,}    0到正无穷   0次到多次

var reg = /\w+/g;    这个+意思是前面的这个变量可以出现一次到多次,这个\w可以重复出现无数次。注意这里不是说\w,而是表达后面的+

var str = "abc"

str.match(reg)        返回[“abc”]

var reg = /\w*/g; “*”号

str.match(reg)        返回[“abc”,""]    匹配了一个空串,因为先看abc符不符合要求,然后还有g呢,g的意思是全局匹配,c后面还有一段距离,叫做逻辑上的距离,到c后面没结束,\w*中的*如果变成0的话,匹配的就是空了,然后在这个逻辑点上往后匹配了一个出来。一开始*变成3,后面变成0了,换句话说正则表达式中匹配的就是空
var reg = /\w*/g;var str = "abc";str.match(reg)
(2) ["abc", ""]

 

var reg = /\d*/g; “*”号    返回4个空

var str = "abc"

str.match(reg)    返回["","","",""]

var reg = /\d*/g;var str = "abc";str.match(reg)
(4) ["", "", "", ""]

返回4个空,逻辑上一开始光标在a的前面匹配出一个空,然后一看a,发现a匹配不了,到了a后面,a后面还是有个空0, 再成0还是一个空,所以有多少个光标定位点就有多少个,所以有4个。上面那个 \w 为什么不是是4个w呢,

一旦\w能识别出值的话,看a能不能识别,b能不能被识别,c能不能被识别,先一连串把能识别的识别掉,到最后的时候才试一下成0,能匹配多久不匹配少的原则,例如现在有一串a

var str = "aaaaaaaaaaaaa"

var reg = /\w+/g;

返回:(2) ["aaaaaaaaaaaaa"]-------------贪婪匹配原则

 

 

贪婪匹配,能匹配多就匹配多,能多就不少。能4个就尽量别三个。

n+ {1 ,----正无穷}

n* {0 ,----正无穷}

n? {0, 1}

var reg = /\w?/g;

“n?”号    能取的就是0-1;

var str = "aaa"    返回[“a”,“a”,"a",“”]

最后还有个空格,因为遇到最后没有a了,那就拿个空

 

n{X}    {x}区间个,定死了多少个,

var reg = /\w{3}/g;    三个三个匹配

var str = "aaaaaaaaa"

 

 

继承方式(原型是构造函数的祖先,是在构造函数的上面)
1.原型链继承方式
    //过多的继承了没有的属性
    Grand.prototype.lastName = 'Grand';
    function Grand(){
        
    }
    var grand = new Grand();
    
    Father.prototype = grand;
    function Father(){
        this.name = 'Father'
    }
    var father = new Father();
    
    Son.prototype = father;
    function Son(){
        
    }
    var son = new Son();


2.构造函数继承(如果囊括方法直接拽过来用)
    //借助被人的方法来用,只能借用构造函数的方法而已。不能继承构造函数的原型,this的原型返回出来还是this.prototype,每次构造出对象都要执行两个方法
    function Person(name,age,sex){
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    function Student (name,age,sex,grade){
        Person.call(this,name,age,sex);//放this的前提是下面new
        this.grade = grade;
    }
    var student = new Student();//不new的话,上面的call中的this没什么意义

 

3.共享原型(A继承B)
    Father.prototype.name = 'lin';
    function Father(){}
    function Son(){}
    function inherit(target,origin){
        target.prototype = origin.prototype;//引用值赋值
    }
    inherit(Son,Father);
    var son = new Son();

4.圣杯模式
    A.通常写法
        function inherit(target,origin){
            function F(){}//
            F.prototype = origin.prototype;//F与origin共用原型
            target.prototype = new F();//与上面一行不能换顺序,想给Son的原型加东西就不会影响到Father的原型,既能继承又不会被改
            target.prototype.constructor = target;//因为target最终继承的是origin的原型,指向了origin的原型,现在要指回到自己的原型
            target.prototype.uber = origin.prototype;//源继承自谁
        }
        Father.prototype.name = 'father';
        inherit(Son,Father);
        function Father(){}
        function Son(){}
        var son = new Son();
        var father = new Father();
        
        //son.__proto__->new F().__proto__->Father.prototype

B.雅虎写法
        var inherit = ( function() {
            var F = function (){};
            return function(target,origin){
                F.prototype = origin.prototype;
                target.prototype = new F();
                target.prototype.constructor = target;
                target.prototype.uber = origin.prototype;
            }
        }())
        Father.prototype.lastName = 'father';
        inherit(Son,Father);
        function Father(){}
        function Son(){}
        var son = new Son();
        var father = new Father();



原文发布时间为:03/13
原文作者: 羊皮卷
本文来源:开源中国 如需转载请联系原作者
上一篇:8.操作系统实战——环境配置,用文件模拟硬盘(生成文件,格式化,安装GRUB,转换虚拟硬盘格式)


下一篇:Win 11 预览版虚拟机安装