JavaScript进阶教程-2.call apply 表格排序 正则

关于函数、原型、dom、this的深入理解

原型深入

dom获取元素

  1. 通过标签获取来的是HtmlCollection,通过标签获取来的都是HtmlCollection类的一个实例
  2. 所有的div都是HTMLDivElement这个类的一个实例>==>HTMLElement==>Element==>Node==>EventTarget==>Object
  3. getElementsByName是定义在document这个家族的方法。
    var p = document.getElementsByName('p'); //通过name获取来的
    var oDiv = document.getElementById('div1');
    var op = oDiv.getElementsByTagName('p'); //通过tag获取来的
    console.dir(p); //p是NodeList的一个实例
    console.dir(op);//op是HtmlCollection这个类的一个实例
    //console.dir({});
    //console.dir([]);
    console.dir(oDiv);
    //所有的div都是HTMLDivElement这个类的一个实例==>HTMLElement==>Element==>Node==>EventTarget==>Object
    var sP = document.getElementById('p'); //通过oDiv来查找getElementsByName的属性,并且让这个属性的值去执行,传入了一个'p'作为参数
    console.dir(sP);

    // document.getElementById('p')  这个getElementById属性是不是方法也是一个函数

函数的三种角色

函数有多种角色:

  1. 普通函数: 函数执行的时候就会产生一个私有的作用域,栈内存。 形参赋值 预解释 代码逐行执行 闭包 内存释放问题
  2. 构造函数(类): new 实例 实力!! 构造函数中的this是当前实例 return问题
  3. 那么函数它自己本身是谁的实例 任何一个函数都是Function这个类的一个实例,那么任何一个函数实例都可以调用(proto)定义在Function这个类原型上的所有属性和方法
    Object.prototype.toString.call();
    var obj = {}; // [object Object]
    var f = new Array(); // ""

call方法深入

call这个方法是定义在Function.prototype的方法。那么我们定义任何一个函数我们都可以认为它是Function这个类的一个实例。那么就可以通过实例的__proto__属性找到所属类的原型。任何一个函数都可以调用call和apply等方法 eg: Object.prototype.toString.call(); 强制改变this关键字的
call作用:
函数实例找到call方法执行,call的执行过程中把调用call方法这个函数实例中的this都改变成call的第一个参数。接下来再把调用call方法的这个实例函数执行

    function fn() { //是Function这个类一个实例
        console.log(this); //obj
    }
    //fn(); // this==>window
    var obj = {
        fn: fn
    }
    //obj.fn();//this ==> obj
    //fn.call(obj); // 1 找到call方法并且运行  2 在运行之前把调用call方法的fn这个函数中的this都修改成call的参数,也就是obj  3 执行fn


    //假如在Function的原型上没有定义一个call,我们自己模拟呢??
    Function.prototype.myCall = function (obj) {
        //把这个函数体内的this都改成obj这个参数
        //执行fn就是this执行
        //console.log(this);
        this(); //因为这个this只有在调用call方法的时候才知道具体是那个函数实例
    }
    //fn.call(obj); //  用obj去借用fn这个方法

    //
    function fn1() {/*console.log(1)*/
       /* this();
        console.log(this)*/
        console.log(1)
    }
    function fn2() {
        console.log(2)
    }
    fn1.call(fn2); //1 在执行的过程中把fn1中的this改成fn2然后fn1()  ==> 1
    /*
    *   上面的fn1.call(fn2)是改变fn1中的this
    * */
    (function (){}).call/*function call()*/.call.call.call.call.call(fn2);
    /*
    *   上面的call是改变function.__proto__.call的call方法中的this
    * *///fn2  这里的fn1只是用来读取值。通过fn1来读取Function.prototype的属性
    //规律: 多个call就是相当于参数执行,而调用call的方法是用来读取call这个属性值的
    //Function.prototype.call(fn1); //Function.prototype是一个匿名函数,但是这个函数什么也没做
   // Function.prototype.call.call.call(fn1); //fn1 ==> fn2.call.call.call(fn1)

call和apply和bind的区别

call在执行的时候,call的第一个参数是用来改变this的,而从第二个参数开始都是传给调用call的函数的

严格模式: call执行的时候和非严格模式不同 没有参数:undefined null:null undefined:undefined,非严格模式都是window
在函数体内的arguments不随着参数变化而变化 arguments.callee arugmetns.caller 不能用
this问题:严格模式自执行函数中的this是undefined,如果没有执行主体this也是undefined。非严格模式下都是window

    `/*'use strict';*/ //严格模式解析代码`
    function sum(num1, num2) {
        //console.log(num1 + num2);
        //console.log(this);
    }
    //sum(100,200); //300 window
    //sum.call(100,200); //从第二个参数开始是传个sum的,我们此时函数已经执行结束了

    //sum.call(); //window
    //sum.call(null); //window
    //sum.call(undefined); //window
    // !function (){console.log(this)}();

apply:它跟call的用法是一样一样的。就是传参数的方式不相同而已
call:是把从第二个参数开始一个一个传给调用call的函数主体
同样也是相当于把数组中的每一项分别传给调用apply这个方法的函数实例

    function sum(num1, num2) {
        console.log(num2 + num1);
        console.log(this);
    }
    //sum.apply(null,[100,200]); //apply的用法,也是把数组参数中的每一项分别传给sum的

绑定 bind: 同样也是用来改变this关键字的

   /* var temp = sum.bind(null, 100, 200);  预处理 中间量  假设 标识变量
    temp();*/
    var obj = {name : 'zx'}
    var temp = sum.bind(obj); //仅仅是改变了this,但是并没有执行 temp已经是被改变了this的函数
    temp(100,200); //当我们需要的时候才执行呢

JSON操作

JSON它是一个特殊的数据格式,是可以跨平台传输的数据

    var obj = {name: 'zf'};
    var jsonObj = {"name" : "tx"};

JSON常用方法:
JSON.stringify() 把json格式的对象转化为字符串的
JSON.parse(); 把json格式的字符串转化为json格式的对象,低版本ie不兼容

    var str = JSON.stringify(jsonObj); //json格式的字符串
    console.log(JSON.parse(str)); //

JSON.png

正则及实战应用

正则的作用

用来判断字符串是否符合规则 处理字符串

  1. test 用来验证是否符合规则返回真和假 ==》 正则匹配
  2. exec 用来把当前字符串中所有符合规则的字符串获取到。 用来实现正则的捕获的。 返回的是一个数组 ==》 正则捕获
    正则的创建:var reg = /\d/; 实例创建: var reg = new RegExp('');
    var reg = /\d/;
    console.log(reg.test('1')); //
    console.log(reg.exec('x')); //
    console.log(reg.exec('1')); //

正则的元字符

    /*
    *   正则由元字符和修饰符组成
    *   1 元字符: 具有一定意义的字符 eg:\d 代表0-9中间的一个数字
    *       特殊意义的元字符:
    *           1 \转义字符
    *           2 ^用某个元字符开头
    *           3 $ 用某个元字符结尾
    *       量词符:
       *       1 *
       *       2 +
       *       3 ?
       *       4 {n}
       *       5 {n,}
       *       6 {n,m}
    *       修饰符:
    *           1 g global全局
    *           2 i ignoreCase忽略大小写
    *           3 m multyline多行
    *
    * */
    var reg = /\\d/;
    reg.test('\d')

编写简单的正则表达式


    var reg1 = /^\d+(ab|cd|xyz)\d+$/;
    var reg2 = /^\d+ab|cd|xyz\d+$/;
    var str1 = '400ab500';
    var str2 = '234ab';
    var str3 = '1324abcd';
    var str4 = 'cd8888ab';
    var str5 = 'xyz999ab';

    //验证邮箱
    //你的网站的邮箱规则
    /*
    *   可以包括数字 字母  下划线 @ 域名 . com/net/cc/cn只能是正常的字母
    *   '.'这个元字符匹配太多需要转义
    *   在[]里的单个的元字符不用转义,就表示这个字母表示的本身的意思
    * */
    var reg =  /^[\w.]+@\w+(\.[a-z]+)?$/i
    /*
    *   问号的几种意义?
    *       1 量词出现0-1次 出现在实际意义字符后边的时候是一个量词
    *       2 贪婪 or 非贪婪   出现在量词后面的问号是修饰贪婪还是非贪婪,如果不加问号那么就是把能匹配多少都拿回来,如果加一个问号。那么是尽可能少的去匹配和捕获 /\d+?/
    *       3 分组中的匹配不捕获也就是子正则中的匹配不捕获,那么就不会出现在exec捕获时候返回的数组中。?: 把问号和冒号放在括号的开始位置。表示不在把括号中的内容当成一个子正则。那么这个分组其实也已经取消了  /^\d(?:ab|cd|ef)\d$/
    *       4 正向预查询和负向预查询  带条件的正则表达式 ?=  ?!负向预查询
    *           eg: 一个字符串有连续多个数字,但是这些数字后边是字母。但是只把满足条件的数组取到,后面的字母忽略。只是一个以字幕结尾这是一个条件,但是不参与捕获      var str2 = 'adsf345qwe#'  这个不行
    *           var  str3 = 'adfa8888aaaa'
    *           var reg = /\d{2,}(?=[a-z]+$)/  切记$符号不要去修饰条件。正向预查询相当于加了一个条件。这个括号里根本就不参与捕获,只是这个正则成立的条件
    *
    * */

    /*
    *   [^a-z] 除了a-z以外的任意字符  var reg = /[^a-z]/;
    *   \d  是0-9  \D 除了0-9之外的任意字符
    *   \w  是[a-zA-Z0-9_]
    *   \W  也是取非集
    *   \s  一切不可见的字符集
    *   \S  取反
    *   . 除了匹配回车之外的单字符
    *
    *
    *   验证重复的字符串  var reg = /(\w)/;  reg.exec()'';
    *                    var reg = /(\w)\1+/
    *
    * */



    /*
    *
    *   分组: 难点+重点
    *       1 什么是分组
    *       2 分组的引用
    *       var reg = /^(\d)(\d)\1$/
    *
    *       用其他方式获取分组捕获的内容
    *       var reg = /(\w)(\w)(\w)/
    *       var str = 'abcdefghijklmn'
    *       reg.test(str);
    *       正则这个方法只要运行了就可以去访问RegExp.$1 - $9 当这个正则实例运行之后,如果此正则上有分组,则自动把捕获到的内容分别赋值给构造函数的$1-$9,如果不够是空字符串 如果是对象类型的找不到才是null 如果是值类型的找不到事空字符串
    *
    *
    *       模式修正符
    *           g
    *           i
    *           m
    *           匹配模式ip地址
    *           192.168.1.1
    *           reg.exec(); 即使你加了g也没有多次都匹配回来
    *           str.match   这个吧所有能匹配来的都匹配来的
    *           这里有一个reg.lastIndex在作怪
    *           str1 = 'qewrqewr8'
    *           str2 = '4adfaasd'
    *           因为上一次匹配的时候的lastIndex是8.下次从8开始找了。但是要用同一个reg实例
    *           正则是尽可能少的去匹配次数,但是却在每次尽可能多的去匹配
    *           加上了全文修饰符g每次lastIndex都会变成0,如果是验证就不要加g了。因为仅仅是为了验证而已
    *
    *           重点replace
    *           var a = [];
    *           str.replace(/\d/g,function (){
    *               return a[arguments[0]]
    *               arguments[0] 当前匹配结果
    *               arguments[1]  当前匹配结果在字符串中的索引
    *               arguments[2]  整个字符串
    *               String.fromCharCode(64+arguments[0]/1)
    *           })
    *
    *
    *
    *           把字符串反转的固定技巧
    *               'abc'.replace(/(\w)(\w)(\w)/,'$3$2$1')
    *
    *
    *            把不限长度的字符串反转 abcdefg
    *            str.replace(/\w/g,function (){
    *               找到第一个用最后一个替换掉
    *               第一个索引位置用arguments[1]; //length-1
    *               str.length-1-arguments[0]
    *               return str.charAt(str.length-1-arguments[1])
    *
    *            })
    *
    *
    *            replace实现字符串去重
    *            var str = '88888888889999999999999997777777777777'
    *
    *
    *
    *
    * */
    var ary = ['a','b','c','d','e'];
    var str = '12345';
    str = str.replace(/\d+/g,function (){
        //console.log(arguments);
        //console.log(]) ;
        return ary[arguments[1]];
    })
    console.log(str);

    var str = '888888888888999999999999997777777777';
    str =  str.replace(/(\d)\1+/g,function (a,b,c,d){
        //如果正则里有了分组就不是3个参数了 是4个参数
        //如果有分组,第一个参数是总正则匹配的记过,第二个参数是子正则匹配的结果
        return b;
    })
    console.log(str)

项目实战-表格排序




    
    
    


    
  • 88
  • 89
  • 78
  • 92
  • 85
  • 97
var utils = {
    listToArray : function (similarArray){
        /*
        *   try catch js
        * */
        var a = [];
        try{
            a = Array.prototype.slice.call(similarArray);
        }catch (e){
            alert(); //ie7 和 8 弹出
            var a = [];
            for(var i=0; i

你可能感兴趣的:(JavaScript进阶教程-2.call apply 表格排序 正则)