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!

  • 相关阅读:
    php第九节课
    php第八节课
    php第七节课
    php第六讲
    php第五节课
    php第四节课
    php第三节课
    Golang Slice切片
    Golang 反射
    Golang 流程控制
  • 原文地址:https://www.cnblogs.com/BetterMan-/p/10165260.html
Copyright © 2011-2022 走看看