zoukankan      html  css  js  c++  java
  • JS知识点整理(二)

    前言

    这是对平时的一些读书笔记和理解进行整理的第二部分,第一部分请前往:JS知识点整理(一)。本文包含一些易混淆、遗漏的知识点,也会配上一些例子,也许不是很完整,也许还会有点杂,但也许会有你需要的,后续会持续更新,喜欢就关注一下喽!

    三、运算符

    3.1运算符

    1.易忽略的例子:

    let obj = { x: 1, y: 2};
    "toString" in obj;   //true  obj继承了toString()方法且in能遍历原型上的不可枚举属性
    
    let arr =[ 3, 6 ,8];
    "0" in arr;          //true  数组包含有0索引属性
    

    2.运算子的不同,导致了不同的语法行为,这种现象称为“重载”(overload)。加号会发生重载,因为加号可当成加法运算,也可作为字符串连接符,而减法,除法和乘法不会发送重载,因为都是作为数学运算使用。

    3.余数运算符(%)的运算结果的正负号由第一个运算子的正负号决定:

    -1 % 2     // -1
    1 % -2     // 1
    10 % 0     // NaN
    10 % '0'   // NaN
    10 % 1     // 0
    2 % 3      // 2
    
    • with:用于设置代码在特定对象中的作用域。

    • eval:可计算某个字符串,并执行其中的的 JavaScript 代码。

    • void:作用是执行一个表达式,然后不返回任何值,或者说返回undefined。

    • 逗号运算符:用于对两个表达式求值,并返回后一个表达式的值。

    'a', 'b'   // "b"
    
    var x = 0;
    var y = (x++, 10);
    x;        // 1
    y;        // 10
    

    5.优先级:!> && > || > 三目运算符,等号优先级较低,逗号优先级更低。

    //例一:
    true || false && false  
    
    //相当于: 
     true || (false && false)    // true
    
    //例二:
    var a = 42, b;
    b = (a++, a);    // 因为括号包了起来,优先级比=高,所以优先运算括号内的结果,先a++,然后再a,得到结果后再赋值给b
    a;    // 43
    b;    // 43
    

    6.三目运算符可适当代替if else。

    四、内置对象

    4.1 Date

    1.Date对象是JavaScript原生的时间库。它以1970年1月1日00:00:00作为时间的零点,可以表示的时间范围是前后各1亿天(单位为毫秒),是构造函数。

    2.直接调用Date总是返回当前时间,为字符串,且传入参数无效:

    Date();   // "Wed Feb 19 2018 16:57:42 GMT+0800 (中国标准时间)"
    Date(2000, 1, 1);   // "Wed Feb 19 2018 16:57:42 GMT+0800 (中国标准时间)"
    

    3.new Date()返回当前日期,为对象,也可接受多种格式的参数,返回一个该参数对应的时间实例:

    • ①不传入参数:
    new Date();   // Wed Dec 19 2018 17:03:59 GMT+0800 (中国标准时间)
    
    • ②参数为时间零点开始计算的毫秒数:
    new Date(1378218728000);   // Tue Sep 03 2013 22:32:08 GMT+0800 (中国标准时间)
    
    • ③参数也可为负整数,代表1970年元旦之前的时间:
    new Date(-1378218728000);   // Fri Apr 30 1926 17:27:52 GMT+0800 (中国标准时间)
    
    • ④参数为多个整数,代表年、月、日、小时、分钟、秒、毫秒:
    new Date(2018, 0, 1, 0, 0, 0, 0);  // Mon Jan 01 2018 00:00:00 GMT+0800 (中国标准时间)
    
    • ⑤参数为日期字符串,可以以空格隔开或者逗号隔开,可以2018,1,2顺序或者1,2,2018顺序,如果输入数值不规范,会自动溢出,如2月没有30号,会自动溢出为3月1号:
    new Date('January 6, 2018');   // Sat Jan 06 2018 00:00:00 GMT+0800 (中国标准时间)
    
    • ⑥只要是能被Date.parse()方法解析的字符串,都可以当作参数:
    new Date('2018-2-15')
    new Date('2018/2/15')
    new Date('02/15/2018')
    new Date('2018-FEB-15')
    new Date('FEB, 15, 2018')
    new Date('FEB 15, 2018')
    new Date('Feberuary, 15, 2018')
    new Date('Feberuary 15, 2018')
    new Date('15 Feb 2018')
    new Date('15, Feberuary, 2018')
    // Thu Feb 15 2018 00:00:00 GMT+0800 (中国标准时间)
    

    4.Date.now():

    //Date.now方法返回当前时间距离时间零点(1970年1月1日 00:00:00 UTC)的毫秒数
    Date.now()  // 1545211158395
    
    Date.now() === new Date().getTime()   // true
    

    5.Date.parse()

    Date.parse方法用来解析日期字符串,返回该时间距离时间零点(1970年1月1日 00:00:00)的毫秒数:

    Date.parse('Aug 9, 2018')
    Date.parse('January 26, 2018 13:51:50')
    Date.parse('Mon, 25 Dec 2018 13:30:00 GMT')
    Date.parse('Mon, 25 Dec 2018 13:30:00 +0430')
    Date.parse('2018-10-10')
    Date.parse('2018-10-10T14:48:00')
    

    6.数据接口一般使用时间戳,因为时间戳在哪个时区都是一样的。

    7.可以将日期的内部表达形式当成一个整数类型的timestamp, 而其他的表达形式只不过是这种内部形式的‘糖衣’,所以new Date()实例的valueOf()返回的是一个timestamp就很容易理解了:

    new Date().valueOf();    // 1542004695697
    // 所以new Date()转换为整型只需要一个加号+,因为会自动调用valueOf()方法。
    
    //以上等同于以下方式:
    var d = new Date();
    d.valueOf();     // 1542004695697 
    d.getTime();    // 1542004695697 
    Date.parse(d);  // 1542004695697 
    Date.now();     // 1542004695697 
    

    8.get方法:

    • getTime():返回实例距离1970年1月1日00:00:00的毫秒数,等同于valueOf方法。
    • getYear():返回距离1900的年数。
    • getFullYear():返回四位的年份。
    • getMonth():返回月份(0表示1月,11表示12月)。
    • getDate():返回实例对象对应每个月的几号(从1开始)。
    • getDay():返回星期几,星期日为0,星期一为1,以此类推。
    • getHours():返回小时(0-23)。
    • getMinutes():返回分钟(0-59)。
    • getSeconds():返回秒(0-59)。
    • getMilliseconds():返回毫秒(0-999)。
    • getTimezoneOffset():返回当前时间与 UTC 的时区差异,以分钟表示,返回结果考虑到了夏令时因素。

    9.set方法:

    • setTime(milliseconds):设置毫秒时间戳。
    • setYear(year): 设置距离1900年的年数。
    • setFullYear(year [, month, date]):设置四位年份。
    • setMonth(month [, date]):设置月份(0-11)。
    • setDate(date):设置实例对象对应的每个月的几号(1-31),返回改变后毫秒时间戳。
    • setHours(hour [, min, sec, ms]):设置小时(0-23)。
    • setMinutes(min [, sec, ms]):设置分钟(0-59)。
    • setSeconds(sec [, ms]):设置秒(0-59)。
    • setMilliseconds():设置毫秒(0-999)。
    var d = new Date();
    
    // 将年份设为去年:
    d.setFullYear(d.getFullYear() - 1);
    
    // 将日期向后推1000天:
    d.setDate(d.getDate() + 1000);
    
    // 将时间设为6小时后:
    d.setHours(d.getHours() + 6);
    

    10.UTC时间比北京时间晚8小时。

    4.2 Math

    1.Math是 JavaScript 的原生对象,提供各种数学功能。该对象不是构造函数,不能生成实例,所有的属性和方法都必须在Math对象上调用。

    2.Math.random()得到的是包括0但不包括1的随机数。

    • ①取随机数: [2, 10)
    Math.random() * 8 + 2;    // 因为至少是大于或等于2,所以要加上2,同时又不能大于10,所以只能乘上8来保证小于8,然后加上2得到小于10的数
    
    • ②取随机数:(2, 10]
    function f() {
        let a = Math.random() * 8 + 2, b;
        b = 12 - a; // a肯定是一个大于等于2但小于10的数,所以b为大于2但小于等于10的数
        return b;
    }
    f();  // 8.199542416221309
    
    • ③取随机数:(2, 10)
    function getNumber() {
        let a = Math.random(), b = 2, c;
        while(a === 0){
            a = Math.random();
        }
        c = a * 8 + b;
        return c;
    } 
    getNumber();   // 6.153494475244344
    
    • ④取随机整数: [2, 10]的整数
    Math.floor(Math.random() * 9 + 2);   // 乘以个数再加上第一个数(第一个可能的值)
    // 加2保证了至少等于2,而随机数乘9能得到不到于9的数,然后两者相加取整后能保证最大就是10
    

    3.Math.max()

    • ①取最大数:
    Math.max.apply(null, [1,2,3]); 
    
    • ②确保一个合法的月份值:
    Math.max(Math.min(1, 'input输入值如果不在1-2的范围内)', 12);
    

    4.3 RegExp

    1.全称:regular expression。

    2.修饰符:g, i, m, u, y

    3.元字符:

    • ①点字符.匹配除回车( )、换行( ) 、行分隔符(u2028)和段分隔符(u2029)以外的所有字符。
    • ^表示字符串的开始位置。 /^test/.test('test123'); // true
    • $表示字符串的结束位置。 /test$/.test('new test'); // true
    • ④竖线符号|在正则表达式中表示"或关系"(OR)。 /11|22/.test('911') // true

    4.量词符:用来设定某个模式出现的次数。

    • ?问号表示某个模式出现0次或1次,等同于{0, 1}
    • *星号表示某个模式出现0次或多次,等同于{0,}
    • +加号表示某个模式出现1次或多次,等同于{1,}
    // t 出现0次或1次
    /t?est/.test('test')  // true
    /t?est/.test('est')   // true
    
    // t 出现0次或多次
    /t*est/.test('test')  // true
    /t*est/.test('ttest') // true
    
    // t 出现1次或多次
    /t+est/.test('test')  // true
    /t+est/.test('ttest') // true
    /t+est/.test('est')   // false
    

    5.转义符:
    需要反斜杠转义的一共有12个字符:^、.、[、$、(、)、|、*、+、?、{、\

    6.特殊字符:

    • [] 匹配退格键(U+0008),不要与混淆
    • 匹配换行键
    • 匹配回车键
    • 匹配制表符 tab(U+0009)
    • v 匹配垂直制表符(U+000B)
    • f 匹配换页符(U+000C)
    • 匹配null字符(U+0000)

    7.字符类: 要放到方括号内才有效,字符类(class)表示有一系列字符可供选择,只要匹配其中一个就可以了,比如[xyz] 表示x、y、z之中任选一个匹配。

    /[abc]/.test('hello world')   // false
    /[abc]/.test('apple')         // true
    

    ①脱字符^:一定是要放到方括号内,要和元字符区分开,如果方括号内的第一个字符是[],则表示除了字符类之中的字符,其他字符都可以匹配:

    /[^abc]/.test('hello world')   // true
    /[^abc]/.test('bbc')           // false
    

    ②连字符-:用来提供简写形式,表示字符的连续范围。

    /a-z/.test('b')     // false
    /[a-z]/.test('b')   // true
    

    8.重复类:使用大括号{}表示,{n}表示恰好重复n次,{n,}表示至少重复n次,{n,m}表示重复不少于n次,不多于m次。

    /lo{2}k/.test('look')       // true
    /lo{2,5}k/.test('looook')   // true
    

    9.预定义模式:指的是某些常见模式的简写方式。

    • d 匹配0-9之间的任一数字,相当于[0-9]
    • D 匹配所有0-9以外的字符,相当于[^0-9]
    • w 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]
    • W 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]
    • s 匹配空格(包括换行符、制表符、空格符等),相等于[ vf]
    • S 匹配非空格的字符,相当于[^ vf]
    •  匹配词的边界
    • B 匹配非词边界,即在词的内部
    // 例:
    /sw*/.exec('hello world');    // [" world"]
    
    /world/.test('hello world');  // true
    /world/.test('hello-world');  // true
    /world/.test('helloworld');   // false
    
    /Bworld/.test('hello-world');  // false
    /Bworld/.test('helloworld');   // true
    var html = "<b>Hello</b>
    <i>world!</i>";
    
    /[Ss]*/.exec(html)[0];      // "<b>Hello</b>
    <i>world!</i>"  [Ss]指代一切字符
    

    ①贪婪模式:默认情况下都是最大可能匹配,即匹配直到下一个字符不满足匹配规则为止。这被称为贪婪模式。

    var s = 'aaa';
    s.match(/a+/) ;  // ["aaa"]
    

    ②非贪婪模式:

    • *?:表示某个模式出现0次或多次,匹配时采用非贪婪模式。
    • +?:表示某个模式出现1次或多次,匹配时采用非贪婪模式。
    var s = 'aaa';
    s.match(/a+?/) ;  // ["a"];
    

    11.组匹配:

    /fred+/.test('fredd');       // true
    /(fred)+/.test('fredfred');  // true
    
    var m = 'abcabc'.match(/(.)b(.)/);
    m;   // ['abc', 'a', 'c']
    
    // 可以用
    引用括号匹配的内容,n是从1开始的自然数,表示对应顺序的括号:
    /(.)b(.)1b2/.test("abcabc");    // true
    /y((..)2)1/.test('yabababab');  // true   1指向外层括号,2指向内层括号
    

    12.正则的实例方法:test()和exec()都是正则放在前面。

    • test()方法返回一个布尔值,表示当前模式是否能匹配参数字符串:
    /cat/.test('cats and dogs') // true
    var r = /x/g;
    var s = '_x_x';
    
    r.lastIndex;   // 0
    r.test(s);     // true
    
    r.lastIndex;   // 2
    r.test(s);     // true
    
    r.lastIndex;   // 4
    r.test(s);     // false
    
    • exec()方法,用来返回匹配结果。如果发现匹配,就返回一个数组,成员是匹配成功的子字符串,否则返回null:
    var s = '_x_x';
    var r1 = /x/;
    var r2 = /y/;
    
    r1.exec(s);   // ["x"]
    r2.exec(s);   // null
    

    13.字符串的实例方法:match()、search()、replace()、split(),正则放在后面。

    • match(): 返回一个数组,成员是所有匹配的子字符串。
    var s = '_x_x';
    var r1 = /x/;
    var r2 = /y/;
    
    s.match(r1);   // ["x"]
    s.match(r2);   // null
    
    // 设置正则表达式的lastIndex属性,对match方法无效,匹配总是从字符串的第一个字符开始:
    var r = /a|b/g;
    r.lastIndex = 7;
    'xaxb'.match(r);   // ['a', 'b']
    r.lastIndex;       // 0
    
    • search():按照给定的正则表达式进行搜索,返回一个整数,表示匹配开始的位置。
    '_x_x'.search(/x/);   // 1
    
    • replace():按照给定的正则表达式进行替换,返回替换后的字符串。
    'aaa'.replace('a', 'b');   // "baa"
    'aaa'.replace(/a/, 'b');   // "baa"
    'aaa'.replace(/a/g, 'b');  // "bbb"  添加修饰符g才会进行整体替换,否则只替换第一个匹配
    'JavaScript'.replace(/([A-Z])/g, '_$&')   // "_Java_Script"  ‘$&’表示所匹配到的文本,所以第一个就相当于匹配到J后,用_J来替换
    let email = 'Betterman@163.com';
    let username = email.replace(/(.*)@.*/, '$1');   // 'Betterman'  截取某段名称
    
    // 回调函数返回所要替换的内容:
    let re = /(.*)@(.*).(.*)/,  glob;
    let callback = function() {
         glob = arguments;
         return arguments[1] + ' at ' + arguments[2] + ' dot ' + arguments[3];
    };
    
    let res = 'Betterman@shenzhen.com'.replace(re, callback); 
    console.log(res);    // Betterman at shenzhen dot com
    console.log(glob);  // ["Betterman@shenzhen.com", "Betterman", "shenzhen", "com", 0, "Betterman@shenzhen.com"]
    // 正则表达式所匹配到的内容  第一组  第二组  第三组  匹配内容所在位置  所进行匹配的字符串(原字符串)
    
    • split():按照给定规则进行字符串分割,返回一个数组,包含分割后的各个成员。
    // 非正则分隔:
    'a,  b,c, d'.split(',');     // [ 'a', '  b', 'c', ' d' ] 注意有空格
    
    // 正则分隔,去除多余的空格:
    'a,  b,c, d'.split(/, */);   // [ 'a', 'b', 'c', 'd' ]
    
    // 指定返回数组的最大成员数:
    'a,  b,c, d'.split(/, */, 2);  // [ 'a', 'b' ]
    
    // 或者:
    let space = 'one, two,three ,four';
    space.split(',');         // ["one", " two", "three ", "four"]   有空格存在
    space.split(/s*,s*/);   // ["one", "two", "three", "four"]    无空格
    

    14.处理文章段落,给行首和行尾用正则raplace(/^/gn,'

    ').replace(/$/gn,'

    ')来加上p标签。

    五、面向对象

    1.面向对象:将真实世界各种复杂的关系,抽象为一个个对象,然后由对象之间的分工与合作,完成对真实世界的模拟。

    2.面向对象具有封装性、继承性、多态性。把同类或者功能整理封装归类,需要什么就去找什么,就相当于把功能封装进对象,我们只是把功能拿来用就行,而不需要了解其实现的原理,对象也不需要知道我们用这个功能来做什么。

    5.1 this

    1.this永远指向最后调用它的那个对象(使用箭头函数除外)。

    2.this判断:优先级

    • ①是否是new绑定;
    • ②是否是显式(硬)绑定,如call、apply、bind;(传入null或undefined时就是想忽略this,会启用默认绑定window,所以最好创建一个空对象来替代,如Object.create(null),这个比{}更空);
    • ③是否是隐式绑定,对象调用这个函数;
    • ④默认绑定,window。

    3.this绑定:

    • call:参数应该是一个对象,如果参数为空、null和undefined,则默认传入全局对象,第一个参数就是this所要指向的那个对象,后面的参数则是函数调用时所需的参数:
    function add(a, b) {
        return a + b;
    }
    add.call(this, 1, 2);   // 3
    
    • apply:与call一样,只是参数为数组而已:
    // 找出数组最大元素
    Math.max.apply(null, [10, 2, 4, 15, 9]);   // 15
    
    • bind:返回一个新函数,而不是像call、apply直接执行返回值。

    5.2 原型与继承

    1.可参考我之前写的一篇博客:彻底弄懂JS原型与继承

    2.创建实例前与创建实例后修改构造函数原型的区别:

    • ①如果在已经生成实例的情况下再给构造函数新创建一个原型,则会切断了构造函数与最初原型的联系,即新原型覆盖了旧原型。但此时实例上的原型依旧指向最初的原型,而不是指向新构建的原型:
    function Person () {}
    let person1 = new Person();
    Person.prototype = {
        constructor: Person,
        name: 'BetterMan',
        age: 26,
        sayName: function(){
            console.log(this.name);
        }
    }
    person1.sayName();   // 报错,实例依旧指向旧原型
    
    • ②如果在创建实例前重写构造函数的原型,实例的原型是指向重写后的原型:
    function Person () {}
    Person.prototype = {
        constructor: Person,
        name: 'BetterMan',
        age: 26,
        sayName: function(){
            console.log(this.name);
        }
    }
    let person1 = new Person(); 
    person1.sayName();    // "BetterMan"
    

    3.__proto__

    • 实例.__proto__ === 构造函数.prototype // true
    • __proto__虽然可以得到实例的原型,但__proto__prototype不是等价的
    • __proto__实际上是实例对象的属性,而prototype是属于构造器函数的属性

    4.__proto__与其说是属性,实际更像是getter/setter,像一个函数,访问a.__proto__时,实际上是调用a.__proto__()__ptoto__是继承自Object.prototype

    Object.definedProperty(Object.prototype, '__proto__', {
       		get: function() {
                    return Object.getPrototypeOf(this);
               },
            set: function(o) {
                    return Object.setPrototypeOf(this, o);
              }
    })
    

    5.几种特殊的原型:

    • ①空对象的原型是 Object.prototype:
    Object.getPrototypeOf({}) === Object.prototype   // true
    
    • ②Object.prototype 的原型是 null:
    Object.getPrototypeOf(Object.prototype) === null   // true
    
    • ③函数的原型是 Function.prototype:
    function f() {}
    Object.getPrototypeOf(f) === Function.prototype   // true
    

    6.Object.create()方法的基本原理:

    function create(o) {  
        function F() {};
        F.prototype = o;
        return new F();
    }
    

    5.3 类

    1.类就像设计师设计出的蓝图,实例就像根据蓝图所建造出来的建筑。

    2.js的类不像标准的类是复制一个副本,它类似于共享。

    3.标准的继承应该是类与类之间的关系,而js的继承时“类”与实例之间的关系,或者应该说是对象与对象之间的关系。

    4.继承的原本意思应该是复制,而js默认是不会复制对象属性的,相反,js会在两个对象之间创建一个关联,这样一个对象就可以通过委托访问另一个对象的属性和函数,进而找到所需要的属性,委托行为意味着某些对象在找不到属性或方法时,会把这个请求委托给另一个对象,这并不是像父类到子类的关系垂直组织的,而是通过任意方向的委托关系并排组织的。

    • ①将B.prototype关联到A.prototype的方法:
    //ES6前:
    B.prototype = new A();
    
    //ES6:
    Object.setPrototypeOf(B.prototype, A.prototype);
    
    • ②判断某个对象的原型链上是否存在某对象:
    //方式一:
    F.prototype.isPrototypeOf(a);
    
    //方式二:
    Object.getPrototypeOf(a) === F.prototype;
    

    最后

    因为比较多,所以目前只整理到这里,后续有些比较重要难懂的模块会分开更新,同时包括ES6的部分,希望对你有所帮助,如有不合理的地方欢迎指正,最后顺口广告来一波:大家好!我是BetterMan, to be better, to be man, better关注BetterMan!

  • 相关阅读:
    Fidder4 顶部提示 “The system proxy was changed,click to reenable fiddler capture”。
    redis 哨兵 sentinel master slave 连接建立过程
    虚拟点赞浏览功能的大数据量测试
    python基础练习题(题目 字母识词)
    python基础练习题(题目 回文数)
    python基础练习题(题目 递归求等差数列)
    python基础练习题(题目 递归输出)
    python基础练习题(题目 递归求阶乘)
    python基础练习题(题目 阶乘求和)
    python基础练习题(题目 斐波那契数列II)
  • 原文地址:https://www.cnblogs.com/BetterMan-/p/10165260.html
Copyright © 2011-2022 走看看