2.ECMAScript

1.发展史、ECMA、编程语言、JS相关、变量、JS值

1.1 五大主流浏览器内核

  • IE: trident
  • Chrome: webkit blink
  • safari: webkit
  • firefox: gecko
  • opera: presto

1.2编程语言

  • 编译型 翻译过程: 源码 -> 编译器 -> 机器语言 -> 可执行的文件
  • 解释型 翻译过程: 源码 -> 解释器 -> 解释一样执行一行

1.3JavaScript

  • ECMAscript: 语法、变量、关键字、保留字、值、原始类型、引用类型运算、对象、继承、函数
  • DOM: document object model W3C规范
  • BOM: browser object model 没有规范

1.4单线程和多线程

js引擎肯定是单线程的但是可以模拟多线程

轮转时间片:短时间内轮流执行多个任务的片段

  1. 任务1 任务2
  2. 切分任务1 任务2
  3. 随机排列这些任务片段,组成队列
  4. 按照这个队列顺序将任务片段送进JS进程
  5. js线程执行一个又一个的任务片段

由于执行的很快,所以给我们的感觉是多线程的

1.5变量

	var a; // 1.变量声明
    a = 3; // 2.变量赋值
    var b = 3; // 3.变量声明并赋值
    var c = a + b; //4.运算大于赋值
    /*
        动态语言 -> 脚本语言 -> 解释型语言 -> 弱类型语言
        静态语言 -> 编译型语言 -> 强类型语言
    */

1.6基本数据类型(原始值)

原始值(基本数据类型)

  • Number:数字
  • String:字符串
  • Boolean:布尔值(true/false)
  • undefined:未被定义的
  • null:空值

1.7引用数据类型(引用值)

  • Object:对象
  • arry:数组
  • function:函数
  • date:日期对象
  • RegExp:正则表达式

1.8 堆内存和栈内存

原始值: 都存在栈内存中 先进后出 数据永久保存不可更改的
在这里插入图片描述

2.基本语法、规范、错误、运算符、判断分支、注释

2.1交换值的问题

 	var a = 1,
        b = 2;
    // 1.
    var c = a;
        a = b;
        b = c;
    // 2.
    a = a +b;
    b = a - b;
    a = a - b;

2.2比较运算符

比较运算符有隐式类型转换, 字符串比较会取对应的ASCII码值进行比较(多个字符从左到右依次对比,直到比较出 ASCII码的大小为止), 小数比较也会取ASCII码从第一位开始比较
NaN与任何东西都不相等包含它自己

2.3逻辑运算符

undefined NaN null 0 ‘’ false除开这些都是真

  • 与 &&:遇到真就往后走返,遇到假或者走到最后了就返回当前值
  • 或 ||:遇到假就往后走,遇到真或者走到最后了就返回当前的值
  • 非 !

3.循环、引用值初识、显示及隐式类型转换

3.1循环

    //1.for循环 
    for(var i = 0; i < 10; i++) {
        console.log(i)
    }
    for(初始胡变量;条件表达式;操作表达式) {
	    循环体
    }
    // 双重for循环,外层循环执行一次,里面循环执行全部
    for(外层初始胡变量;外层条件表达式;外层操作表达式) {
	    循环体1
        for(里层初始胡变量;里层条件表达式;里层操作表达式) {
            745874循环体2
        }
    }
    /*
    步骤:
        1.声明变量i = 0
        2.if(i < 10) {
            log(i)
        }
        3. i++
        4.i = 1了
        5.if(i < 10) { 不满足条件时停止循环
            log(i)
        }
        6. i++
    */
    // break 退出循环
    // continue 结束本次循环,直接继续执行下次循环

    // 2.while循环
    while(条件表达式) {
	    循环体
    }
    var a = 1;
    while(a < 10) {
        num++
    }
    // do while循环
    do{
	    循环体
    } while(条件表达式)
    // dowhile至少会执行一次循环体,因为先do做后while判断

用来计数跟次数相关的用for while和dowhile用来做更复杂的

3.2 typeof()

console.log(typeof(typeof(a)))–string因为typeof返回值是字符串格式
可以打印出 number string boolean object undefined function

3.3显示类型转换

  • Number()强制转换
  • parseInt()转换成整型,必须以数字开头否则返回NaN,不四舍五入
  • parseFloat()转为数字,可转换小数,如果无法转换则返回NaN
  • toFixed()保留几位小数,会四舍五入
  • String()转字符串
  • toString()转字符串–undefined和null无toString方法
  • Boolean()代表空、否定的值会被转成false 例如0,NaN,Null,’’,undefined其余的全是true

3.4隐式类型转换

  • ++, --, *, /, %, -, >, <, >=, <=, ==, !=
  • isNaN()检查其参数是否是非数字值-也会先进行隐式转换

4.函数基础、函数种类、形实参及映射、变量类型

4.1函数

编程最基本原则:高内聚()、低耦合(重复代码提取出来,成为一个独立的模块)

    // 最基本的函数写法 - 函数声明式
    function test('形参') {
        // 函数执行语句
    }
    // 匿名函数表达式   函数字面量
    var fn = function ('形参') {
        // 函数执行语句
    }
    // 注:函数都需要return 不写的话js会默认在最后添加一个return语句来终止函数
    function test(a, b) {
        a = 3;//函数内部可以更改实参的值(实参没传值的不可修改)
        b = 4;
        console.log(arguments[0])
    }
    text(1)

4.2案例

	// 1.n的阶乘(不能循环) -> 递归
    function fact(n) {
        if(n === 1) return 1;
        return n * fact(n - 1)
    }
    //2.斐波那契数列(不能循环)
    function fb(n) {
        if(n <= 2) return 1;
        return fb(n -1) + fb(n - 2)
    }

5.函数参数默认值、递归、预编译流程、原理、现象、暗示全局变量

5.1初始化参数

	function test(a, b) {
        // es6之前的常用兼容写法
        var a = arguments[0] || 1;
        var b = arguments[1] || 2;
    }
    test()

5.2递归

一个函数内部调用自己就是递归,记住递归一定要有结束条件要不就是死循环了

    function fn(x) {
        if(x > 0) {
            return x + fn(x-1)
        } else {
            return 0
        }
    }
    fn(3)
    /*  解析
        fn(3) = 3 + fn(3-1)
              = 3 + 2 + f(2-1)
              = 3 + 2 + 1 + f(1-1)
    */

5.3预编译

  1. 检查通篇的语法错误
  2. 预编译的过程
  3. 解释一行执行一行

函数声明整体提示, 变量只有声明提升

5.4函数执行上下文(Activation Object)

  1. 创建AO对象(Activation Object)函数上下文
  2. 找形参和变量声明,将形参名和变量作为AO属性名,值为undefined
  3. 将实参值赋值给形参
  4. 在函数体里面找函数声明, 值赋予函数体
  5. 执行
	function test(a) {
        console.log(a);
        var a = 1;
        console.log(a);
        function a() {}
        console.log(a);
        var b = function (){}
        console.log(b);
        function d(){}
    }
    test(2)
    /*
        函数执行上下文
        AO = {
            a: undefined -> 2 -> function a() {}
            b: undefined
            d: function d() {}
        }
        执行
        AO = {
            a: undefined -> 2 -> function a() {} -> 1
            b: undefined -> function (){}
            d: function d() {}
        }
    */
	function test(a, b) {
        console.log(a); // 1  
        c = 0;
        var c;
        a = 5;
        b = 6;
        console.log(b); //6
        function b() {}
        function d() {}
        console.log(b); //6
    }
    test(1)
    /*   函数执行上下文
         AO = {
             a: undefined -> 1
             b: undefined -> function b() {}
             c: undefined
             d: function d() {}
         }
         执行
         AO = {
            a: undefined -> 1 -> 5
            b: undefined -> function b() {} -> 6
            c: undefined -> 0
            d: function d() {}
         }
    */

5.5全局执行上下文(global Object)

  1. 创建GO对象(global object)全局上下文
  2. 找变量声明,将变量名作为GO属性名,值为undefined
  3. 找函数声明,作为GO属性,值赋予函数体
  4. 执行
	var a = 1;
    function a() {
        console.log(2);
    }
    console.log(a);
    /*
         GO = {
             a: undefined -> function a(){} -> 1
         }
    */
	var b = 3;
    console.log(a);//function a() {...}
    function a(a) {
        console.log(a);//function a() {}
        var a = 2;
        console.log(a);//2
        function a() {}
        var b = 5;
        console.log(b);
    }
    a(1)
    /*
        GO = {
            b: undefined,
            a: function a() {...}
        }
        AO = {
          a: undefined -> 1 -> function a() {}
          b: undefined -> 5
        }
    */
	a = 1;
    function test() {
        console.log(a);// undefined
        a = 2;
        console.log(a);//2
        var a = 3;
        console.log(a); //3
    }
    test()
    var a;
    /*
        GO = {
            a: undefined -> 1
            test: function test() {...}
        }

        AO ={
            a: undefined -> 2 -> 3
        }
    */
	function test() {
        console.log(b);//undefined
        if (a) {
            var b = 2;
        }
        c = 3;
        console.log(c);//3
    }
    var a;
    test()
    a = 1;
    console.log(a);//1
    /*
        GO = {
            a: undefined -> 1
            test: function test(){...} 
            c: 3
        }
        AO = {
            b: undefined
        }
    */

注意:预编译期间不看if

	a = 1;
    function test(e) {
        function e(){}
        arguments[0] = 2;
        console.log(e); //2
        if(a) {
            var b = 3;
        }
        var c;
        a = 4
        var a;
        console.log(b);//undefined
        f = 5;
        console.log(c);//undefined
        console.log(a);//4
    }
    var a;   
    test(1)
    /*
         GO = {
             a: undefined -> 1
             test: function test(){}
             f: 5
         }
         AO = {
             e: undefined -> 1 -> function e(){} -> 2
             b: undefined
             c: undefined
             a: undefined -> 4
         }
    */

5.6面试题

	if (typeof (a) && (-true) + (+undefined) + '') {
        console.log('通过')
    } else {
        console.log('没通过');
    }
    /*
        解析:
        typeof(a)返回字符串undefined所以是真
        -true: -1
        +undefined: NaN
    */ 
   console.log(!!' ' + !!'' - !!false || '通过')
   // true + false - false     

6.作用域、作用域链、预编译、闭包基础

6.1作用域([[scope]])

  • 函数创建时, 生成的一个JS内部的隐士属性
  • 函数存储作用域链的容器, 作用域链里存储着AO/GO, 函数执行完以后, AO是要销毁的, 每次执行函数都会生产一个新的AO, 函数执行完AO便会销毁, 也就是说AO是一个即时的存储容器
	function a() {
        function b() {
            var b = 2;
        }
        var a = 1;
        b()
    }
    var c = 3;
    a()

注:每个函数的作用域链都是包含GO的–每一个函数在被定义的时候就包含了全局执行上下文GO

图解
1.当函数被定义时

每一个函数在被定义的时候它的作用域链都有全局执行上下文(GO)

2.当函数被执行前一刻(预编译)

3.当b函数被定义时

4.当b函数被执行的前一刻(预编译)

5.当b函数被执行结束的时候


6.当a函数被执行结束的时候

全局执行的前一刻生成GO, -> 函数声明已经定义了
当函数被定义的时候已经形成了作用域([[scope]]) -> 作用域链([[scope chian]]) -> GO
当函数被执行的前一刻生成自己的AO

	function a() {
        function b() {
            function c() {

            }
            c()
        }
        b()
    }
    a()
    /*
        1.a定义 -> a.[[scope]] -> [[scope chian]] -> 0:GO
        2.a执行 -> a.[[scope chian]] -> 0:a的AO -> 1:GO

        3.b定义 -> b.[[scope]] -> [[scope chian]] -> 0:a的AO -> 1:GO
        4.b执行 -> b.[[scope]] -> [[scope chian]] -> 0:b的AO -> 1:a的AO -> 2:GO

        5.c定义 -> c.[[scope]] -> [[scope chian]] -> 0:b的AO -> 1:a的AO -> 2:GO
        6.c执行 -> c.[[scope]] -> [[scope chian]] -> 0:c的AO -> 1:b的AO -> 2:a的AO -> 3:GO

        7.c结束 -> c.[[scope]] -> [[scope chian]] -> 0:b的AO -> 1:a的AO -> 2:GO
        8.b结束 -> b.[[scope]] -> [[scope chian]] -> 0:a的AO -> 1:GO -> 同时c.[[scope]]不存在了
        9.a结束 -> a.[[scope]] -> [[scope chian]] -> 0:GO -> 同时b.[[scope]]不存在了
    */

6.2闭包

    function test1() {
        function test2() {
            var b = 2;
            console.log(a)
        }
        var a = 1;
        return test2()
    }
    var c = 3;
    var test3 = test1()
    test3()

图解
1.当test1函数被定义时

2.当test1函数被执行前一刻(预编译), 函数test2被定义

3.当test1函数被执行结束

4.当test3被执行

5.当test3执行结束

当内部函数被返回到外部并保存时,一定会产生闭包,闭包一定会产生原来的作用域链不释放(不销毁),过度的闭包可能会导致内存泄漏,或加载过慢

7.立即执行函数、闭包深入、逗号运算符

7.1立即执行函数

自动执行, 执行完成后立即释放

    // 写法1(看起来比较清晰)  
    (function() {

    })();
    // 写法2(w3c建议)
    (function(){

    }());
    // 一定是表达式才能被执行符号()执行

立即执行函数也又返回值, 需要用变量接收

    var num = (function (a, b) {
        return a + b
    }(2, 3));
    console.log(num);

()包起来的一定是表达式
函数声明变成表达式的方法: + - ! || &&

	function test() {
        var arr = [];
        for (var i = 0; i < 10; i++) {
            arr[i] = function () {
                document.write(`${i}->`)
            }
        }
        return arr
    }
    var myArr = test()
    console.log(myArr);
    for (j = 0; j < 10; j++) {
        myArr[j]()
    }
    //打印结果为10个10
    // 因为return arr形成了闭包
	var fn = (
        function a() {
            return 1
        },
        function b() {
            return '1'
        }
    )()
    console.log(typeof(fn))//str

    var a = 10;
    if(function b(){}) {
        a += typeof(b)
    }
    console.log(a)//
    /*
    (function b(){})因为被括号包起来了,所以变成了表达式,函数名就忽略了,所以typeof b是undefined
    */

8.对象、构造函数、实例化

8.1对象

	var person = {
        name: '张三,
        age: 14,
        sex: '男',
        teach: function() {
            console.log('1')
        }
    }
    delete person.sex
    delete person.teach 

对象内部的函数最好叫方法
delete用于删除对象中的属性

	// 对象字面量
    var obj = {
        name: '张三',
        age: 19
    }
    obj.age = 20

8.2构造函数

	// 系统自带的构造函数 -> 与对象字面量是一样的
    var obj = new Object();
    obj.name = '张三';
    obj.sex = '男'
    // 自定义构造函数
    function Teacher() {
        this.name = '冷然';
        this.age = 18;
        this.weight = 120
        this.smoke = function () {
            this.weight--
            console.log(this.weight)
        }
        this.eat = function () {
            this.weight++
            console.log(this.weight)
        }
    }
    var teacher1 = new Teacher()
    var teacher2 = new Teacher()
    teacher1.smoke()
    teacher1.smoke()
    console.log(teacher2.weight);

实例化的每个构造函数相互都是不关联的

	// 自定义构造函数传参
    function Teacher(name, sex, weight) {
        this.name = name;
        this.sex = sex;
        this.weight = weight
    }
    var teacher1 = new Teacher('张三', '男', 120)
    var teacher2 = new Teacher('李四', '女', 90)
    console.log(teacher1);
    console.log(teacher2);
    // 最优写法
    function Teacher(option) {
        this.name = option.name;
        this.sex = option.sex;
        this.weight = option.weight
    }
    var teacher1 = new Teacher({
        name: '刘能',
        sex: '男',
        weight: 140
    })
    var teacher2 = new Teacher({
        name: '赵四',
        sex: '女',
        weight: 125
    })
    console.log(teacher1);
    console.log(teacher2);

9.构造函数及实例化原理、包装类

9.1构造函数中的this

实例化之前this指向window 实例化之后this指向为当前实例化对象而不是构造函数本身

    function Car(color, brand) {
        this.color = color;
        this.brand = brand;
        // 隐士加了return this
    }
    var car1 = new Car('red', 'Benz')
    /*
        1.当构造函数被实例化的时候, 就相当于普通函数执行
        2.当AO生成后内部默认有个this:{}
        GO = {
            Car: function Car(){...}
            car1: undefined -> { color: 'red', brand: 'Benz'}
        }
        AO = {
            this: {
                color: color,
                brand: brand
            }
        }
    */
    // 模拟构造函数
    function Car(color) {
        var me = {}
        me.color = color
        return me
    }
    var car = Car('red')

9.2包装类

一般情况原始值并没有自己的方法和属性

    var a = 1;
    console.log(a); //1
    var b = new Number(a)
    console.log(b); //Number {1}
    b.name = '冷然'
    console.log(b); //Number {1, name: "冷然"}
    console.log(b + 1); // 参与运算时b会回到原始值
    // 经过new Number后就实例化了一个对象, 就叫数字对象/对象字 
  • new Number() 转换成数字对象
  • new String() 转换成字符串对象 ->有length属性
  • new Boolean() 转换成布尔对象

null undefined是不可设置任何的属性和方法的

   // JS包装类问题
    var a = 123;
    a.len = 3;
    console.log(a.len)//undefined
    /*
        1.首先看见a是个原始值
        2.然后给a加了个len的属性,js引擎认为你不对
        3.new Number(123).len = 3 但是保存不了所以只能 delete
        4.因为已经变成数字对象的所以打印a.len是undefined
    */
	// 数组截断方法
    var arr = [1, 2, 3, 4]
    arr.length = 2;
    console.log(arr) //1,2

9.3面试题

	// 1. 
    var name = 'lengran'
    name += 10 //lengran10
    var type = typeof(name)//string
    //var type = new String(typeof(name))
    if(type.length === 6) {
        // new String(type).text = 'string'但是无法保存所delete
        type.text = 'string'
    }
    console.log(type.text);//undefined

    // 2.
    var x = 1,
        y = z = 0;
    function add(n) {
        return n = n + 1;
    }
    y = add(x)
    function add(n) {
        return n = n + 3;
    }
    z = add(x)
    console.log(x, y, z);
    /*
        GO = {
            x: undefined -> 1
            y: undefined -> 0 -> 4
            z: 0 -> 4
            add: function add(){n + 1} -> function add(){n + 3}
        }
    */

   // 3.哪个能打印12345
    function foo1(x) {
        console.log(arguments);
        return x
    }
    foo1(1, 2, 3, 4, 5)
    function foo2(x) {
        console.log(arguments);
        return x
    } (1, 2, 3, 4, 5);
    (function foo3(x) {
        console.log(arguments);
        return x
    })(1, 2, 3, 4, 5)

    // 4.
    function b(x, y, a) {
        a = 10
        console.log(arguments[2]);
    }
    b(1, 2, 3)

10.原型、原型链、闭包和立即执行函数、插件开发初识

10.1原型

原型(prototype)其实是function对象的一个属性, 但是prototype也是个对象

   function Handphone(color, brand) {
        this.color = color
        this.brand = brand
        this.screen = '18:9'
        this.system = 'Android'
    }
    Handphone.prototype.rom = '64G'
    Handphone.prototype.ram = '6G'
    Handphone.prototype.screen = '16:9'//自身有的属性不会查找原型

    var phone1 = new Handphone('red', '小米')
    var phone2 = new Handphone('black', '华为')
    console.log(phone1)
    console.log(phone2)

所有被构造函数构造出来的对象都可以继承原型上的属性和方法

   // 动态参数写在构造函数内部
    function Handphone(color, brand) {
        this.color = color
        this.brand = brand
    }
    // 静态参数写在原型上继承就可以了(或者一些方法)
    Handphone.prototype.rom = '64G'
    Handphone.prototype.ram = '6G'
    Handphone.prototype.screen = '18:9'
    Handphone.prototype.system = 'Android'
    Handphone.prototype.call = function() {
        console.log('我正在打电话')
    }

    var phone1 = new Handphone('red', '小米')
    var phone2 = new Handphone('black', '华为')
    console.log(phone1)
    console.log(phone2)

    // 简化prototype写法
    Handphone.prototype = {
        rom: '64G',
        ram: '6G',
        screen: '18:9',
        system: 'Android',
        call: function() {
            console.log('我正在打电话')
        }
    }

通过实例化对象不能对prototype进行增删改

	function Handphone(color, brand, system) {
        this.color = color
        this.brand = brand
        this.system = system
    }
    functin Test(){}
    Handphone.prototype = {
        constructor: Test
    }
    console.log(Handphone.prototype);

Handphone.prototype上的constructor指向构造函数本身(可以进行修改)

	function Car() {
        /*  __proto__是属于实例化对象的
            var this = {
                __proto__: Car.prototype
            }
        */
    }
    Car.prototype.name = '宝马'
    var car = new Car()
    console.log(car)

__proto__是属于每个实例化对象的, proto就是键名用来保存prototype

	function Person() {}
    Person.prototype.name = '张三'
    var p1 = {
        name: '李四'
    }
    var person = new Person()
    console.log(person.__proto__);
    person.__proto__ = p1
    console.log(person.__proto__);

__proto__是可以被修改的但是没有意义
原型本身也有它自己的原型

10.2. 闭包的另一种方式

	function test() {
        var a = 1;
        function plus1() {
            a++
            console.log(a);
        }
        window.plus = plus1
    }
    test()
    plus()

10.3.插件

防止全局和函数作用域污染, 因为ES5没有块级所以用立即函数隔离

	// js插件写法 
    //;作用:写多个立即执行函数不报错
    ;(function () {
        function Test() {
            this.name = 1234
        }
        window.Test = Test
    })()
    var test = new Test()
    console.log(test);

11.原型与原型链深入、对象继承

11.1原型链

	function Professor() {}
    Professor.prototype.tSkill = 'JAVA'
    var professor = new Professor()

    function Teacher(){
        this.mSkill = 'JS/JQ'
    }
    Teacher.prototype = professor
    var teacher = new Teacher()
    
    function Student() {
        this.pSkill = 'HTML/CSS'
    }
    Student.prototype = teacher
    var student = new Student()
    console.log(student);

沿着原型(_proto)一级一级继承查找叫做原型链
原型链的顶端是Object().prototype
子原型不能修改父原型的原始值 引用值可以修改
普通函数默认返回undefined 构造函数通过实例化以后默认返回this

11.2Object.create(对象 || null)

创建对象, 自定义原型

	function Test() {};
    Test.prototype.num = 1;
    var obj1 = Object.create(Test.prototype)
    var obj2 = new Test()
    console.log(obj1);
    console.log(obj2);

不是所有对象都继承与Object.prototype, Object.create(null)不继承
undefined null 不可以使用toString方法

11.3.call/apply

	function test() {
        console.log(1)
    }
    // 系统隐士的加了个call 
    test.call()

call/apply都是更改this指向唯一的区别就是apply后面的参数以数组传递

	function Car(brand, color) {
        this.brand = brand;
        this.color = color;
        this.run = function() {
            console.log('running');
        }
    }
    var newCar = {
        cc: 3.0
    }
    Car.call(newCar, 'Benz', 'red')
    Car.apply(newCar, ['Benz', 'red'])
    console.log(newCar);
    var car = new Car('Benz', 'red')
    console.log(car);
	 // call/apply例子
    function Compute() {
        this.plus = function (a, b) {
            console.log(a + b);
        }
        this.minus = function (a, b) {
            console.log(a - b);
        }
    }
    function FullCompute() {
        Compute.apply(this)
        this.mult = function (a, b) {
            console.log(a * b);
        }
        this.div = function (a, b) {
            console.log(a / b);
        }
    }
    var fullCompute = new FullCompute()
    fullCompute.plus(4, 2)
    fullCompute.minus(4, 2)
    fullCompute.mult(4, 2)
    fullCompute.div(4, 2)

12.对象继承深入、call_apply、圣杯模式、构造函数和闭包、企业模块化

12.1.解决原型链继承和隔离的问题

如果teacher的prototype和student的prototype直接相等的话, student修改原型也会同样修改teacher的原型,
解决方法如下, 用一个中间实例对象这就叫做圣杯模式

	function Teacher() {
        this.name = '张三',
        this.tSkill = 'JAVA'
    }
    Teacher.prototype = {
        pSkill: 'JS/JQ'
    }
    var t = new Teacher()
    console.log(t);
    function Student() {
        this.name = '李四'
    }
    function Buffer() {}
    Buffer.prototype = Teacher.prototype
    var buffer = new Buffer()
    Student.prototype = buffer
    Student.prototype.age = 18
    var s = new Student()
    console.log(s);
    // 封装
    Teacher.prototype.name = '刘能 ';
    function Teacher(){}
    function Student(){}
    inherit(Student, Teacher)
    Student.prototype.age = '18 '
    var t = new Teacher()
    var s = new Student()
    console.log(t);
    console.log(s);
    function inherit(target, origin) {
        function Buffer() { }
        Buffer.prototype = origin.prototype;
        target.prototype = new Buffer()
        target.prototype.constructor = target
        target.prototype.super_calss = origin
    }
    // 企业级封装
    var inherit = (function() {
        var Buffer = function(){}
        return function(target, origin) {
            Buffer.prototype = origin.prototype;
            target.prototype = new Buffer()
            target.prototype.constructor = target;
            target.prototype.super_calls = origin
        }
    })()

13.链式调用、对象属性与遍历、this指向、caller、callee

13.1.链式调用

    var sched = {
        wakeup: function() {
            console.log('跑步')
            return this
        },
        morning: function() {
            console.log('吃饭')
            return this
        },
        night: function() {
            console.log('睡觉')
        }
    }
    sched.wakeup().morning()

13.2.对象枚举/遍历

    var car = {
        brand: 'Benz',
        color: 'red',
        displacement: '3.0',
        lang: '5',
        width: '2.5'
    }
    for( var key in car) {
        console.log(`${key}${car[key]}`);
    }

13.hasOwnProperty

找对象自身的属性,排除原型的属性

    function Car() {
        this.brand = 'Benz';
        this.color = 'red';
        this.cc = '3.0';
    }
    Car.prototype = {
        lang: 5,
        width: 2.5
    }
    Object.prototype.name = "Object"
    var car = new Car()
    for (var key in car) {
        if (car.hasOwnProperty(key)) {
            console.log(car[key]);
        }
    }

    // 第二种查找对象里是否有某个属性
    function Car() {
        this.brand = 'Benz';
        this.color = 'red';
    }
    Car.prototype = {
        width: 2.5
    }
    // in是不排除原型的
    console.log('width' in car) 

13.4.instanceof

判断这个对象是否是该构造函数实例化出来的

     function Car() {}
    var car = new Car()
    console.log(car instanceof Car);//true
    function Person() {}
    var p = new Person()
    console.log(car instanceof Person)//false
    console.log(car instanceof Object)//true
    console.log([] instanceof Array)//true
    console.log([] instanceof Object)//true
    console.log({} instanceof Object)//true
	// 第二种方法 常用
    var a = []
    var str = Object.prototype.toString.call(a)
    if(str === '[object Array]') {
        console.log('是数组')
    } else {
        console.log('不是数组')
    }

13.5.this

普通函数和全局的this默认指向window

    function test(b) {
        this.d = 3; //window.d = 3
        var a = 1;
        function c() {}
    }
    test(123)
    /*
        AO = {
            arguments: [123]
            this: window
            b: undefined -> 123
            a: undefined
            c: function c(){}
        }
    */
	function Test() {
        /*
        *var this. = {
        *   __proto__: Test.prototype
        *}
        *
        */
        this.name = '123'
    }
    var test = new Test()
    /*
    *   AO= {
    *     this: {
    *       name: '123',
    *       __proto__: Test.prototype
    *     }
    *   }
    * 
    * 
    *   GO = {
    *     Test: function() {}
    *     test: {
    *         name: '123'
    *         __proto__: Test.prototype
    *     }
    *   }
    */

13.6.call/apply

	function Person() {
        this.name = '张三',
        this.age = 18
    }

    function Programmer() {
        Person.apply(this)
        this.work = 'Programmer'
    }
    var p = new Programmer()
    console.log(p)

13.7.callee/caller

	function test() {
        console.log(arguments.callee)
        console.log(arguments.callee.length)//形参
        console.log(test.length)//形参
        console.log(arguments.length)//实参
    }
    function sum(n) {
        if(n <= 1) return 1;
        return n + sum(n - 1)
    }
    sum()
    var sum = (function(n) {
        if(n <= 1) return 1;
        return n + arguments.callee(n - 1)
    })(10)
    console.log(sum);

caller调用当前函数的函数引用,如果是全局作用于中调用当前的函数就返回null, 严格模式下会报错

	// A函数调用B函数(b中有caller),则caller返回值为A函数
    function test1() {
        test2()
    }
    function test2() {
        console.log(test2.caller)
    }

13.8.1typeof返回值

number str obj(null) boolean undefined function\

13.8.2打印结果

	undefined == null //true
    undefined === null//false
    isNaN('100')//false
    parseInt('1a') == 1//true
	var a = 5;
    function test() {
        a = 0;
        console.log(a);
        console.log(this.a);
        var a;
        console.log(a);
    }
    test()//0 5 0
    new test()//0 undefined 0

14.三目运算、对象克隆、浅拷贝、深拷贝

14.1三目运算符/三元运算符

  	var a = 5,
        str = '';
    str = a > 0 ? (a > 3 ? '大于3' : '小于等于3') : '小于等于0'

14.2.浅拷贝/浅复制/浅克隆

浅拷贝: 只能处理第一层属性, 不能拷贝内层引用值

	Object.prototype.num = 1;
    var person1 = {
        name: '张三',
        age: 18,
        son: {
            first: 'Tom',
            second: 'Lucy'
        }
    }
    var person2 = clone(person1)
    person2.name = '李四'
    person2.son.third = 'Ben'
    console.log(person1);
    console.log(person2);
    function clone(origin, target) {
        var tar = target || {}
        for (var key in origin) {
            if (origin.hasOwnProperty(key)) {
                tar[key] = origin[key]
            }
        }
        return tar
    }

14.3.深拷贝/深复制/深克隆

	Object.prototype.num = 1;
    var person1 = {
        name: '张三',
        age: 18,
        children: {
            first: {
                name: '刘能',
                age: 40
            },
            second: {
                name: '赵四',
                age: 46
            }
        },
        car: ['奔驰', '宝马']
    }
    var person2 = deepClone(person1)
    person2.car.push('奥迪')
    console.log(person1);
    console.log(person2);
    function deepClone(origin, target) {
        var target = target || {},
            toStr = Object.prototype.toString,
            arrType = '[object Array]';
        for (var key in origin) {
            if (origin.hasOwnProperty(key)) {
                if (typeof (origin[key]) === 'object' && origin[key] !==null) {
                    if (toStr.call(origin[key]) === arrType) {
                        target[key] = []
                    } else {
                        target[key] = {}
                    }
                    deepClone(origin[key], target[key])
                } else {
                    target[key] = origin[key]
                }
            }
        }
        return target
    }

15.深拷贝实例、数组基础、数组方法、数组排序

15.1.数组基础

本章方法都是操作原数组

	// 1.数组字面量-常用
    var arr1 = [];
    // 2.内置构造函数声明
    var arr2 = new Array();
    // 3.不使用的
    var arr3 = Array()

所有数组都继承于Array.prototype, index: 数组元素的下标(索引值), 从零开始

15.2.稀松数组

	var arr = [,1, 3, 5, 7,]
    var arr1 = new Array(5)//[empty*5]
    console.log(arr);//[empty,1, 3, 5, 7]
    console.log(arr.length);//5
    var arr3 = [1,2,3,4,5,6,7,8,9,10]
    console.log(arr3[10]);//undefined
  • new Array(5): 创建一个长度为5的空数组
  • new Array(5.2): 报错length属性不正确
  • new Array(a): a is notdefined
  • new Array(‘a’): 创建一个数组[‘a’]
  • new Array(1,2,3): 创建一个数组[1,2,3]
  • new Array(,1,3,): 语法错误

15.3.push/unshif

  • push在数组最后一位加, 返回值是执行了方法后数组的长度 可以加多个值
  • unshif在数组最前面加, 返回值是执行了方法后数组的长度 可以加多个值
	var arr = [1, 2, 3]
    arr.push(4)
    arr.push(4, 5, 6)
    Array.prototype.myPush = function() {
        for(var i = 0; i < arguments.length; i++) {
            this[this.length] = arguments[i]
        }
        return this.length
    }
    
    console.log(arr.myPush(4, 5, 6));

15.4.pop/shift/reverse

  • pop 删除数组最后一位并且返回删除的元素
  • shift 删除数组第一位并且返回删除的元素
  • reverse 反转数组

15.5.splice

  • index:参数1 从何处添加或删除元素(开始项下标)
  • howmany:参数2 剪切长度,必须是数字,可以为0(为0则不剪切)
  • item*n: 要添加到数组的新元素(从剪切位置开始添加)

返回值被删除的元素

	var arr = ['a', 'b', 'c']
    console.log(arr.splice(1, 1, 1,2,3));
    console.log(arr);
    var arr = ['a', 'b', 'c', 'e']
    arr.splice(3, 0, 'd')
    arr.splice(-1, 0, 'd')
    console.log(arr);

15.6.sort

用于对数组进行排序(按照ASCII码来排列), 默认升序(字母和数字)

	 var arr = [27, 49, 5, 7]
    //必须有返回值: 1.负值 a就排前面 2.正值 b就排前面 
    arr.sort(function (a, b) {
        // if(a > b) {
        //     return 1
        // } else {
        //     return -1
        // }
        // 升序
        return a - b;
        // 降序
        return b - a;
    })
    console.log(arr);
	// 随机排序
    var arr = [1, 2, 3, 4, 5, 6]
    arr.sort(function(a,b) {
        // var rand = Math.random()//返回0-1但不包含0和1
        // return rand - 0.5 > 0 ? 1 : -1
        return Math.random() - 0.5;
    })
    console.log(arr);

15.7.面试题

	function Foo() {
        getName = function() {
            console.log(1);
        }
        return this
    }
    Foo.getName = function () {
        console.log(2);
    }
    Foo.prototype.getName = function() {
        console.log(3);   
    }
    var getName = function() {
        console.log(4);
    }
    function getName() {
        console.log(5);
    }
    // 相当于调用Foo对象下面的getname所以是2
    Foo.getName()//2
    getName()//4
    // 执行了Foo后getname重新赋值了
    Foo().getName()//1
    getName()//1
    // 点优先级高于new,相当于new 2new就没用可以不看了
    new Foo.getName()//2 
    // new Foo()括号优先级最高, 所以带着new一起执行了
    //因为本身this没getname所以拿了原型的
    new Foo().getName()//3
    // 同上第一个new直接忽略了
    new new Foo().getName()//3

16.数组方法、类数组

concat

concat链接两个或多个字符串或数组
本章方法都是生成一个新数组

    var arr1 = ['a', 'b', 'c']
    var arr2 = ['d', 'e', 'f']
    var arr3 = arr1.concat(arr2)
    console.log(arr1);
    console.log(arr3);

slice

在数组中读取指定元素

    var arr = [1, 2, 3, 4, 5]
    console.log(arr.slice(0,4));
  • start: 开始读取下标(包含当前下标数) 不传截取到最后, 负数从后面开始
  • end 结束下标(不包含当前下标数) 不传截取到最后

join

把数组中的所有元素转换为一个字符串,参数就是元素分隔符(可选)

    var arr = ['a', 'b', 'c', 'd']
    var str1 = arr.join('-')
    var arr1 = str1.split('-')
    console.log(arr1);

split

    var arr = ['a', 'b', 'c', 'd']
    var str1 = arr.join('-')
    var arr1 = str1.split('-', 2)
    console.log(arr1);

把一个字符串分割成字符串数组

  • 参数1 分隔符
  • 参数2 指定返回数组的最大长度(length)

类数组

类数组的原型是Obejct而数组的原型是Array

    function test() {
        console.log(arguments);
    }
    test(1,2,3,4,5)
    var oDiv = document.getElementByTagName('div')

笔试题

    // 数组去重
    Array.prototype.unique = function() {
        
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值