前端入门一之ES6--面向对象、够着函数和原型、继承、ES5新增方法、函数进阶、严格模式、高阶函数、闭包

时间:2024-11-13 11:58:33

前言

  • JS是前端三件套之一,也是核心,本人将会更新JS基础、JS对象、DOM、BOM、ES6等知识点,这篇是ES6;
  • 这篇文章是本人大一学习前端的笔记;
  • 欢迎点赞 + 收藏 + 关注,本人将会持续更新。

文章目录

  • JS高级 + ES6
      • 1、面向对象
        • 1.1、对象
        • 1.2、类
          • 1.2.1、创建类
          • 1.2.2、构造函数
          • 1.2.3、类中添加方法
        • 1.3、类的继承
        • 1.4、super关键字
          • 1.4.1、调用父类的构造函数
          • 1.4.2、调用父类的普通函数
        • 1.5、三个注意点
        • 1.6、面向对象tab案例
      • 2、构造函数和原型
        • 2.1、概述
        • 2.2、构造函数
          • 2.2.1、静态和实例成员
          • 2.2.2、构造函数的问题
        • 2.3、构造函数原型prototype
        • 2.4、对象原型
        • 2.5、constructor构造函数
        • s2.6、构造函数、实例、原型对象三者的关系
        • 2.7、原型链查找原则
        • 2.8、原型对象this指向
        • 2.9、扩展内置对象
      • 3、继承
        • 3.1、call()
        • 3.2、借用构造函数继承父类型属性
        • 3.3、借用原型对象继承父类型方法
        • 3.3、类的本质
      • 4、ES5新增方法
        • 4.1、数组方法
          • 4.1.1、forEach()
          • 4.1.1、filter() 筛选数组
          • 4.1.3、some()
        • 4.2、字符串方法、
        • 4.3、对象方法
          • 4.3.1、Object.keys()
          • 4.3.2、Object.defineProperty()
      • 5、函数进阶
        • 5.1、函数的定义方式
        • 5.2、函数的调用方法
        • 5.3、函数里面this的指向
        • 5.4、改变函数内部this指向
          • 5.4.1、call()方法
          • 5.4.1、apply()方法
          • **因此apply主要跟数组有关系,比如Math.max()求数组的最大值**
          • 5.4.3、bind()方法 (重点)
          • 5.4.4、总结(call() \ apply() \ bind() )
            • 主要运用场景
      • 6、严格模式
        • 6.1、开启严格模式
          • 6.1.2、为脚本开启严格模式
          • 6.1.2、为函数开启严格模式
      • 7、严格模式中的变化
        • 7.1、变量规定
        • 7.2、严格模式下this指向问题
        • 7.3、函数变化
      • 8、高阶函数
      • 9、闭包
        • 9.1、变量作用域
        • 9.2、什么是闭包
        • 9.3、在chrome中调试闭包
        • 9.4、闭包作用
        • 9.5、闭包练习
          • 9.5.1、点击li输出索引号
          • 9.5.2、定时器中的闭包

JS高级 + ES6

1、面向对象

面向对象的思维特点 :

  1. 抽取(抽象)对象共用的属性和行为组织(封装)成一个类
  2. 对类进行实例化,获取类的对象
1.1、对象

在技术中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象

对象是由属性方法组成的

  • 属性:事物的特征,在对象用属性来表示
  • 方法:事物的行为,在对象中用方法来表示
1.2、类

ES6中怎加了类的概念,可以用class关键字说明一个类

  • 抽象了对象的公共部分,它指一个大类
  • 对象特指某一个,通过类实例化一个具体的对象
1.2.1、创建类
class name {
    
}
  • 创建实例
var xx = new name();

注意:类必须使用new实例化对象

1.2.2、构造函数

constructor()方法是类的构造函数(默认方法),用于传递参数,返回实例对象,通过new命令生成对象实例时候,会自动调用该方法。

  • 通过class关键字创建类,类名我们还是习惯性定义首之母大写
  • 类里面有个constructor函数,可以接受传递过来的参数,同时返回实例对象
  • constructor函数只要new生成实例时,就会调用这个给函数,如果不写,类也会自动生成这个函数
  • 命名注意点:
    • 创建类->类名后不要加小括号
    • 生成实例->类名后面加小括号
    • 构造函数不需要加function关键字
//如:创建一个class类
<script>
class Star {
        constructor(uname,age) {
            this.uname = uname;
            this.age = age;
        }
}
    
    //2.创建对象
    var ldh = new Star('ldh',18);
</script>
1.2.3、类中添加方法

语法:

<script>
class Person {
        constructor(name,age) {
            this.name = name;
            this.age = age;
        }
        say() {
            console.log(this.name + 'hello');
        }
}
    var ldh = new Person('ldh',18);
    ldh.say();
</script>

注意:方法之间不能加逗号,同时方法不需要添加function关键字

  • 类共有的属性放到constructor里面
  • 类里面的函数都不需要写function关键字
1.3、类的继承

程序的继承:子类可以继承父类的一些属性和方法。

语法:

//父类
class Father {
    
}
//子类
class Son extends Father {
    
}

实例:

<script>
class Father {
        constructor(x , y) {
            this.x = x;
            this.y = y;
		}
        sum() {
            console.log(this.x + this.y);
        }
    }
    //子类继承父类,同时扩展方法
class Son extends Father P{
        consturctor(x,y) {
            //利用super 调用父类的构造函数
            //super 必须在子类this之前调用
            super(x,y);
            this.x = x;
            this.y = y;
        }
        subtract() {
            console.log(this.x - this.y);
		}
}
    var son = new Son(5,3);
    son.sum;
</script>
1.4、super关键字
  • super关键字用于访问和调用对象父类上的函数,可以调用父类的构造函数,也可以调用父类的普通函数
  • 注意1.4.1 和 1.4.2的调用方法
1.4.1、调用父类的构造函数

注意:子类在构造函数中使用super,必须放到this前面。

如:

<script>
//父类
class Father {
    constructor(surname) {
        this.surname = surname;
    }
    saySurname() {
        console.log(this.surname);
    }
} 
//子类继承父类
 class Son extends Father {
     constructor(surname,firstname) {
         super(surname);  //注意
         this.firstname = firstname;
     }
     sayFirstname() {
         console.log(this.firstname);
     }
}
    var d = new Son('l','dh');
    d.saySurname();
    d.sayFirstname();
</script>
1.4.2、调用父类的普通函数

语法:

<script>
    calss Father {
        say() {
            return 'father';
        }
    }
    class Son extends Father {
        return super.say();   //注意
    }
</script>
1.5、三个注意点
  1. 在ES6类没有变量提升,所以必须先定义类,才通过类实例化对象
  2. 类里面的共有属性和方法一定要加this 使用
  3. 类里面的this指向:
    • constructor 里面的this指向指向对象
    • 方法里面的this指向这个方法的调用
1.6、面向对象tab案例

2、构造函数和原型

2.1、概述

类就是对象的模板,对象就是类的实例。

ES6之前,对象不是基于类创建的,而是用一种构建函数的特殊函数来定义和它们的特征。

  • 创建对象有三种方法
    • 字面量创建对象
    • new Object()
    • 自定义构造函数
<script>
    //1.
    var obj1 = new Object();
    //2.
    var obj2 = {
        
    };
    //3.
    function Star(uname,age) {
        this.uname = uname;
        this.age = age;
        this.sing = function() {
            console.log('');
}
}
    var l = new Star('l',18);
</script>
2.2、构造函数
2.2.1、静态和实例成员
<script>
    function Star(uname,age) {
        this.uname = uname;
        this.age = age;
        this.song = function() {
            console.log('l');
        }
    }
    //实例成员
    var ldh = new Star('l',18);
    //静态成员
    Star.sex = 'man';
</script>
2.2.2、构造函数的问题

问题:浪费内存

在这里插入图片描述

2.3、构造函数原型prototype
<script>
    function Star(uname,age) {
        this.uname = name;
        this.age = age;
    }
    Star.prototype.sing = function() {
        console.log('l');
    }
    var ldh = new Star('l',18);
</script>
  • 构造函数通过原型分配函数所有对象都是共享的,没有内存浪费
  • js中,每一个构造函数都有一个prototype属性
  • prototype属性是一个对象
  • 把不变得方法定义在prototy对象上

原型是啥? 原型对象作用?

一个对象 共享方法

2.4、对象原型

在这里插入图片描述

  • Star.prototype 和 ldh.__proto__指向相同
<script>
    function Star(uname,age) {
        this.uname = uname;
        this.age = age;
    }
    Star.prototype.sing = function() {
        console.log('l');
	}
    var ldh = new Star('l',18);
    console.log(Star.prototype == ldh._proto_);     //true
</script>
2.5、constructor构造函数
  • 对象原型(_proto_)(左右两边是两个下划线)和构造函数(prototype)原型对象里面都有一个consrtuctor属性
  • constructor主要用于指向该对象哪一个构造函数
<script>
    function Star(uname,age) {
        this.uname = uname;
        this.age = age;
	}
    //注意
    Star.prototype = {
        //这个要注意
        constructor: Star;
        sing: function() {
            console.log('l');
        }
    movie: function() {
        console.log('m');
    }
    }
</script>
s2.6、构造函数、实例、原型对象三者的关系
  • __proto__constructor属性是对象所独有的; prototype属性是函数所独有的

在这里插入图片描述

2.7、原型链查找原则

在这里插入图片描述

  1. 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性
  2. 如果没有找到就查找原型_proto_ 指向的prototype对象
  3. 如果还没有就查找原型对象的模型(object的原型对象)
  4. 依次推直到 null
2.8、原型对象this指向
  • 构造函数中this指向我们的实例对象
  • 原型对象里面放的是方法,这个方法里面的this指向的是这个方法的调用者,也就是这个实例对象
2.9、扩展内置对象
  • 可以通过原型对象,对原来的内置对象进行扩展自定义的方法
  • 如:
<script>
    Array.prototype.sum = function() {
        var sum = 0;
        for(var i = 0;i < this.length;i++) {
            sum += this[i];
        }
        return sum;
    }
    var str = [1,2,3];
    str.sum();
</script>

注意

  • 数组和字符串内置对象不能给原型对象覆盖操作Array.prototype = {},只能是Array.prototype.xxx = function(){}的方式

3、继承

ES6 之前并没有给我们提供extends继承

  • 构造函数 + 原型对象模拟实现继承,称为组合继承
3.1、call()

调用这个函数,并且修改函数运行时的this指向

fun.call(thisArg,arr1,arr2,……);
  • thisArg:当前调用函数this指向
  • arg1,arg2:传递的其他参数

<script>
    function fn(x,y) {
        console.log(this);
        console.log(x + y);
    }
    var o = {
        name: 'pig';
    }
    fn.call(o,1,2);
    //fn.call(); 也可以调用函数
</script>
3.2、借用构造函数继承父类型属性
  • 核心原理:通过call()把父类型的this指向子类型的this,这样就可以实现子类继承父类的属性
<script>
    function Father(uname,age) {
        this.uname = uname;
        this.age = age;
    }
    function Son(uname,age,sex) {
        //继承父亲的属性  在this前
        Father.call(this,uname,age);
        this.sex = sex;
    }
    var son = new Son('l',18,'man');
    
</script>
3.3、借用原型对象继承父类型方法
  • 一般情况下,对象的方法都在构造函数的原型对象设置,通过构造函数无法继承父类方法

核心原理:

  1. 将子类所共享的方法提取出来,让子类 prototype 原型对象 = new 父类()
  2. 本质:子类原型对象等于实例化父类,因为父类实例化会另外开票空间
  3. 将子类的consructor重新指向子类的构造函数
<script>
    function Father(uname,age) {
        this.uname = uname;
        this.age = age;
    }
    Father.prototype.money = function() {
        console.log(100000);
    }
    function Son(uname,age,sex) {
        Father.call(Son,uname,age);
        this.sex = sex;
    }
    //直接 Son.prototype = Father.prototype; 这样会修改子类的原型对象
    Son.prototype = new Father();
    //如果利用对象修改了原型对象
    Son.prototype.constructor = Son;
</script>
3.3、类的本质
  1. class本质还是function
  2. 类的所有方法都定义在类的prototype属性上
  3. 类创建的实例,里面也有_proto_指向类的prototype原型对象

4、ES5新增方法

ES5给我们新增了一些方法,可以方便操作数组或者字符串

  • 数组方法
  • 字符串方法
  • 对象方法
4.1、数组方法
  • 遍历方法:foreach(),map(),filter(),some,every();
4.1.1、forEach()
array.forEach(function(currentValue,index,arr));
  • currentValue:数组当前项的值
  • index:数组当前项的索引
  • arr:数组对象本身
<script>
    var arr = [1,2,3,4,5,6,7,8,9];
    var sum = 0;
    arr.forEach(function(Valude,index,arr)) {
                console.log('每个数组元素' + value);
    			console.log('每个数组元素的' + index);
    			console.log('数组本身' + array);
    			sum += value;
                }
</script>
4.1.1、filter() 筛选数组
<script>
    array.filter(function(currentValue,index,arr)) {
                 
                 }
</script>
  • filter( ) 方法创建一个新数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
  • 返回一个新数组
<script>
    var arr = [12,66,34,24,134];
    var newArr = arr.filter(function(value,index)) {
        return value % 2 === 0;                
        }
</script>
4.1.3、some()
  • some()方法用于检测数组中的元素是否满足指定条件
  • 返回:是布尔值,找到了 true,没有就是false
  • 且注意:找到了满足条件的第一个元素,则终止循环,不在寻找
<script>
    var arr = [1,2,3,4,5];
    var flag = arr.some(function(value)) {
                        return value === 2;
                        }
</script>
4.2、字符串方法、
  • trim()方法会从一个字符串的两端删除空白字符串
  • trim方法不会影响字符串本身,他返回的是一个新的字符串
<body>
    <input type = "text" > <button>
    点击
    </button>
    var str = '   an  dy   ';
    var str1 = str.trim();
    //获取元素
    var input = document.querySelector('input');
    var btn = document.querySelector('button');
    var div = document.querySelector('div');
    btn.onclick = function() {
    var str = input.value.trim();
    if(str == ' ') {
    alert('please input');
    } else {
    div.innerHTML = str;
    }
    }
</body>
4.3、对象方法
4.3.1、Object.keys()
  • Object.keys()用于获取对象自身所有的属性
  • 效果类似for……in
  • 返回:一个由属性名组成的数组
  • 返回:
<script>
    var obj = {
        name: 'pig',
        age: 18,
        sex: 'man'
    };
    var arr =