Bootstrap

前端JS高级部分(包含ES6新增特性)

前端JS高级

1.对象与类

对象

对象是由属性和方法组成的:是一个无序键值对的集合,指的是一个具体的事物

属性:事物的特征,在对象中用属性来表示(常用名词)

方法:事物的行为,在对象中用方法来表示(常用动词)

类抽象了对象的公共部分,它泛指某一大类(class)对象特指某一个, 通过类实例化一个具体的对象

创建类

语法:
class name{
constructor( ){ ..... }
.....
}
var 变量名 = new name();

constructor构造函数

可以接受传递过来的参数,同时返回实例对象 ,只要 new 生成实例时,就会自动调用这个函数, 如果我们不写这个 函数,类也会自动生成这个函数

类创建添加属性和方法

 // 1. 创建类 class  创建一个 明星类
        class Star {
            // 类的共有属性放到 constructor 里面
            constructor(uname, age) {
                this.uname = uname;
                this.age = age;
            }
            sing(song) {
                // console.log('我唱歌');
                console.log(this.uname + song);

            }
        }

        // 2. 利用类创建对象 new
        var ldh = new Star('刘德华', 18);
        var zxy = new Star('张学友', 20);
        console.log(ldh);
        console.log(zxy);
        // (1) 我们类里面所有的函数不需要写function 
        //(2) 多个函数方法之间不需要添加逗号分隔
        ldh.sing('冰雨');
        zxy.sing('李香兰')

类的继承

class son extends father { … }

 // 1. 类的继承
        // class Father {
        //     constructor() {

        //     }
        //     money() {
        //         console.log(100);

        //     }
        // }
        // class Son extends Father {

        // }
        // var son = new Son();
        // son.money();
        class Father {
            constructor(x, y) {
                this.x = x;
                this.y = y;
            }
            sum() {
                console.log(this.x + this.y);

            }
        }
        class Son extends Father {
            constructor(x, y) {
                super(x, y); //调用了父类中的构造函数
            }
        }
        var son = new Son(1, 2);
        var son1 = new Son(11, 22);
        son.sum();
        son1.sum();

关键字super

用于访问和调用对象父类上的函数,必须在子类this之前调用

 // super 关键字调用父类普通函数
        class Father {
            say() {
                return '我是爸爸';
            }
        }
        class Son extends Father {
            say() {
                // console.log('我是儿子');
                console.log(super.say() + '的儿子');
                // super.say() 就是调用父类中的普通函数 say()
            }
        }
        var son = new Son();
        son.say();
        // 继承中的属性或者方法查找原则: 就近原则
        // 1. 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
        // 2. 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
        // 3.如果子类想要继承父类的方法,同时在自己内部扩展自己的方法,利用super 调用 父类的构造函数,super 必须在子类this之前调用

this的指向

  1. constructor中的this指向的是new出来的实例对象
  2. 自定义的方法,一般也指向的new出来的实例对象
  3. 绑定事件之后this指向的就是触发事件的事件源

insertAdjacentHTML( ‘position’ , text)

可以直接把字符串格式添加到父元素中,和element.append(‘内容’)和element.prepend(‘内容’)类似

position插入的位置:

1.beforebegin: 元素自身前面 2.afterend: 元素自身后面

3.afterbegin: 元素内部第一个子节点之前 4.beforeend: 元素内部最后一个子节点之后

text: 插入的内容

鼠标双击事件

element.ondblclick 但双击会默认选中文字 解决方法插入下面代码:

 // 双击禁止选定文字
     window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();

双击文本框让文字内容处于选中状态

input.select();

2.构造函数和原理、继承、新增方法

构造函数和原型

静态成员和实例成员

实例成员 :构造函数内部通过this添加的成员

静态成员:在构造函数本身上添加的成员 比如:构造函数名.静态成员名 = ’ 内容 ';

,静态成员只能 通过构造函数来访问 比如:构造函数名.静态成员名

构造函数原型prototype

构造函数通过原型分配的函数是所有对象所共享的,每一个构造函数都有一个prototype 属性,指向另一个对象。这个 prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有

可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可 以共享这些方法

对象原型

对象都会有一个属性 _ _ proto _ _ 指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有 _ _ proto_ _ 原型的存在

_ _ proto_ _对象原型和原型对象 prototype 是等价的

_ _ proto_ _对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是 它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象 prototype

constructor构造函数

对象原型( _ _ proto_ _)和构造函数(prototype)原型对象里面都有一个属性 constructor 属性 ,constructor 我们称为构造函数,因为它指回构造函数本身。

constructor 主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来 的构造函数。

一般情况下,对象的方法都在构造函数的原型对象中设置。如果有多个对象的方法,我们可 以给原型对象采取对象形式赋值,但是这样就会覆盖构造函数原型对象原来的内容,这样修 改后的原型对象 constructor 就不再指向当前构造函数了。此时,我们可以在修改后的 原型对象中,添加一个 constructor 指向原来的构造函数

原型链

①ldh 对象实例 ——(ldh._ _ proto_ _ )——>

②Str原型对象 prototype ——(prototype. _ _ proto_ _ )——>

③ object原型对象prototype ——(prototype. _ _ proto_ _ )——>

④null

构造函数实例和原型对象三角关系

①ldh 对象实例 ——(ldh._ _ proto_ _ )——>

②Str原型对象 prototype ——(star.prototype.constructor)——>

③构造函数 ——>①

③构造函数 ——( star.prototype )——> ② Str原型对象 prototype

原型对象中this指向

构造函数中的this和原型对象的this,都指向我们new出来的实例对象

继承

call()

语法:函数名.call( thisArg, arg1 , arg2…)

thisArg:当前调用函数this的指向对象

arg1 , arg2…:传递的其他参数

子构造函数继承父构造函数中的属性借用原型对象继承方法

 <script>
        // 借用父构造函数继承属性
        // 1. 父构造函数
        function Father(uname, age) {
            // this 指向父构造函数的对象实例
            this.uname = uname;
            this.age = age;
        }
        Father.prototype.money = function() {
            console.log(100000);

        };
        // 2 .子构造函数 
        function Son(uname, age, score) {
            // this 指向子构造函数的对象实例
            Father.call(this, uname, age);
            this.score = score;
        }
        // Son.prototype = Father.prototype;  这样直接赋值会有问题,如果修改了子原型对象,父原型对象也会跟着一起变化
        Son.prototype = new Father();
        // 如果利用对象的形式修改了原型对象,别忘了利用constructor 指回原来的构造函数
        Son.prototype.constructor = Son;
        // 这个是子构造函数专门的方法
        Son.prototype.exam = function() {
            console.log('孩子要考试');

        }
        var son = new Son('刘德华', 18, 100);
        console.log(son);
        console.log(Father.prototype);
        console.log(Son.prototype.constructor);
    </script>

ES5新增方法

forEach遍历数组

arr.forEach(function(value, index, array) {
//参数一是:数组元素
//参数二是:数组元素的索引
//参数三是:当前的整个数组  })
//相当于数组遍历的 for循环 没有返回值

filter过滤数组

var arr = [1,2,3,4,5];
arr.filter(function(value, index, array) {
//参数一是:数组元素
//参数二是:数组元素的索引
//参数三是:当前的整个数组
  	return value <=2;
})
console.log(newArr);//[1,2] //返回值是一个新数组

some查找数组

some 查找数组中是否有满足条件的元素
var arr = [10, 30, 4];
var flag = arr.some(function(value,index,array) {
//参数一是:数组元素
//参数二是:数组元素的索引
//参数三是:当前的整个数组
	return value < 3;   }); 
console.log(flag);//false返回值是布尔值,只要查找到满足条件的一个元素就立马终止循环

some和forEach区别

1.如果查询数组中唯一的元素, 用some方法更合适,在some 里面 遇到 return true 就 是终止遍历 迭代效率更高

2.在forEach 里面 return 不会终止迭代

去除字符串两端的空格

str.trim()

获取对象的属性名

Object.keys(对象名) //获取到当前对象中的属性名 ,返回值是一个数组

Object.defineProperty设置或修改对象中的属性

Object.defineProperty(对象名,'修改或新增的属性名',{
		value:修改或新增的属性的值,
		writable:true/false,//如果值为false 不允许修改这个属性值          					enumerable: false,//enumerable 如果值为false 则不允许遍历                  configurable: false  //configurable 如果为false 则不允许删除这个属性  属性是否可以被删除或是否可以再次修改特性 }) 

3.this、严格模式、高阶函数、闭包、递归、正则表达式

函数内部的this指向

调用方式this指向
普通函数调用window
构造函数调用实例对象 原型对象里面的方法也指向实例对象
对象方法调用该方法所属对象
事件绑定方法绑定事件对象
window
window

改变函数内部 this 指向

1.call()方法

语法:函数名.call( thisArg, arg1 , arg2…)

thisArg:当前调用函数this的指向对象

arg1 , arg2…:传递的其他参数

2.apply()方法

语法:fun.apply( thisArg, [argsArray] )

thisArg: 在fun函数运行时指定的this值

argsArray: 传递的值,为数组形式

3.bind()方法

语法:fun.bind( thisArg, arg1,arg2… ) //不会调用函数,但能改变函数内部this指向

thisArg: 在fun函数运行时指定的this值

arg1 , arg2…:传递的其他参数

返回由指定的this值和初始化参数改造的原函数拷贝

三者的异同

共同点 : 都可以改变this指向

不同点: 1.call 和 apply 会调用函数, 并且改变函数内部this指向;

  1. call 和 apply传递的参数不一样,call传递参数使用逗号隔开,apply使用数组传递
  2. 3.bind 不会调用函数, 可以改变函数内部this指向.

开启严格模式

在所有语句或者函数内部最前面添加 ’ use strict ';

高阶函数

高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。

闭包

闭包(closure)指有权访问另一个函数作用域中变量的函数。简单理解就是 ,一个作 域可以访问另外一个函数内部的局部变量。

代码示例:
  <script>
  		//3秒后打印li的内容
        // var lis = document.querySelectorAll('li');
        // for (var i = 0; i < lis.length; i++) {
        //     (function(i) {
        //         setTimeout(function() {
        //             console.log(lis[i].innerHTML);

        //         }, 3000)
        //     })(i);
        // }

        // 计算打车价格
        var car = (function() {
            var price = 5;
            var begin = 13;
            return {
                price: function(n) {
                    if (n <= 3) {
                        return begin;
                    } else {
                        return (n - 3) * price + begin;
                    }
                }
            }
        })();
        console.log(car.price(5));
    </script>

递归

如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。简单理解:函 数内部自己调用自己, 这个函数就是递归函数

代码示例:
 <script>
 		//利用递归求斐波那契数列
        function fn(n) {
            if (n == 1 || n == 2) {
                return 1;
            }
            return fn(n - 1) + fn(n - 2);
        }
        console.log(fn(6));
    </script>

正则表达式的创建

var rg = /123/;

正则表达式测试

var rg = /123/; 
console.log(rg.test(123));//匹配字符中是否出现123  出现结果为true console.log(rg.test('abc'));//匹配字符中是否出现123 未出现结果为false

边界符

1.^:表示匹配行首的文本(以谁开始)

2.$:表示匹配行尾的文本(以谁结束)

如果 ^和 $ 在一起,表示必须是精确匹配。

var rg = /abc/; // 正则表达式里面不需要加引号 不管是数字型还是字符串型 
// /abc/ 只要包含有abc这个字符串返回的都是true 
console.log(rg.test('abc')); 
console.log(rg.test('abcd')); 
console.log(rg.test('aabcd')); 
console.log('‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐'); 
var reg = /^abc/; console.log(reg.test('abc')); // true console.log(reg.test('abcd')); // true
console.log(reg.test('aabcd')); // false
console.log('‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐');
var reg1 = /^abc$/; // 精确匹配 要求必须是 abc字符串才符合规范 console.log(reg1.test('abc')); // true
console.log(reg1.test('abcd')); // false
console.log(reg1.test('aabcd')); // false
console.log(reg1.test('abcabc')); // false

字符类

字符类表示有一系列字符可供选择,只要匹配其中一个就可以了。所有可供选择的字符 都放在方括号内。

[ ]方括号

表示有一系列字符可供选择,只要匹配其中一个就可以了

var rg = /[abc]/; // 只要包含有a 或者 包含有b 或者包含有c 都返回为true console.log(rg.test('andy'));//true
console.log(rg.test('baby'));//true
console.log(rg.test('color'));//true
console.log(rg.test('red'));//false
var rg1 = /^[abc]$/; // 三选一 只有是a 或者是 b  或者是c 这三个字母才返回  true console.log(rg1.test('aa'));//false
console.log(rg1.test('a'));//true
console.log(rg1.test('b'));//true
console.log(rg1.test('c'));//true
console.log(rg1.test('abc'));//true ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐var reg = /^[a‐z]$/ //26个英文字母任何一个字母返回 true  ‐ 表示的是a 到z 的范 围   console.log(reg.test('a'));//true
console.log(reg.test('z'));//true
console.log(reg.test('A'));//false ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
//字符组合
var reg1 = /^[a‐zA‐Z0‐9]$/; // 26个英文字母(大写和小写都可以)任何一个字母返回  true   ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
//取反 方括号内部加上 ^ 表示取反,只要包含方括号内的字符,都返回 false 。 var reg2 = /^[^a‐zA‐Z0‐9]$/;
console.log(reg2.test('a'));//false
console.log(reg2.test('B'));//false
console.log(reg2.test(8));//false
console.log(reg2.test('!'));//true

量词符

量词说明
*重复>=0次
+重复>=1次
?重复0次或1次
{n}重复n次
{n,}重复>=n次
{n,m}重复n到m次

预定义类

预定类说明
\d匹配0-9之间任一数字,相当于[0-9]
\D匹配所有0-9以外的字符,相当于[ ^0-9]
\w匹配任意的字母、数字和下划线, 相当于[A-Za-z0-9]
\W匹配所有字母、数字和下划线以外的字符, 相当于[ ^A-Za-z0-9]
\s匹配空格(包括换行符、制表符、空格符等),相当于[\t\r\n\v\f]
\S匹配非空格的字符,相当于[ ^\t\r\n\v\f]

正则替换replace

replace() 方法可以实现替换字符串操作,用来替换的参数可以是一个字符串或是一个正 则表达式

stringObject.replace( / 表达式 / switch, replacement )

表达式 :被替换的字符串或正则表达式

switch:g–全局匹配; i–忽略大小写; gi–全局匹配+忽略大小写

replacement:替换为的字符串

返回值是一个替换完毕的新字符串

4.ES6语法

let

1.使用let关键字声明的变量才具有块级作用域,使用var声明的变量不具备块级作用 域特性

2.使用let关键字声明的变量没有变量提升,要先声明才能使用

const

用来声明常量,常量就是值(内存地址)不能变化的量

1.具有块级作用域 ,声明 const时候必须要给定值

2.如果是常量不能重新进行赋值,如果是基本数据类型,不能更改值,如果是复杂数据 类型,不能更改地址值

解构赋值

ES6中允许从数组中提取值,按照对应位置,对变量赋值,对象也可以实现解构

1.解构赋值就是把数据结构分解,然后给变量进行赋值

2.如果结构不成功,变量跟数值个数不匹配的时候,变量的值为undefined

3.数组解构用中括号包裹,多个变量用逗号隔开,对象解构用花括号包裹,多个变量用 逗号隔开

箭头函数

() => {} //():代表是函数; =>:必须要的符号,指向哪一个代码块;{}:函数体
const fn = () => {}//代表把一个函数赋值给fn

1.函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号

2.如果形参只有一个,可以省略小括号

3.箭头函数不绑定this关键字,箭头函数中的this,指向的是函数定义位置的上下文this

剩余参数

function sum (first, ...args) {
	console.log(first); // 10      
	console.log(args); // [20, 30]   
}  
sum(10, 20, 30);

Array 的扩展方法

扩展运算符 //扩展运算符可以将数组或者对象转为用逗号分隔的参数序列

let ary = [1, 2, 3];
...ary  // 1, 2, 3
console.log(...ary);    // 1 2 3,相当于下面的代码
console.log(1,2,3)

构造函数方法:Array.from()

将伪数组或可遍历对象转换为真正的数组

//定义一个集合
let arrayLike = {
	'0': 'a',    
	'1': 'b',    
	'2': 'c',    
	length: 3 
}; 
//转成数组
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

该方法还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理, 将处理后的值放入返回的数组

find()

用于找出第一个符合条件的数组成员,如果没有找到返回undefined

let ary = [{
	id: 1,
	name: '张三'
}, {
	id: 2,
	name: '李四'
}];
let target = ary.find((item, index) => item.id == 2);//找数组里面符合条件 的值,当数组中元素id等于2的查找出来,注意,只会匹配第一个

findIndex()

用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1

let ary = [1, 5, 10, 15];
let index = ary.findIndex((value, index) => value > 9);
console.log(index); // 2

includes()

判断某个数组是否包含给定的值,返回布尔值。

[1, 2, 3].includes(2) // true
[1, 2, 3].includes(4) // false

String 的扩展方法

模板字符串 //用反引号

let name = '张三';  let sayHello = `hello,my name is ${name}`; // hello, my name is zhangsan模板字符串中可以解析变量、换行、调用函数

startsWith() 和 endsWith()

表示参数字符串是否在原字符串的头部/尾部,返回布尔值

repeat()

repeat方法表示将原字符串重复n次,返回一个新字符串

Set 数据结构

类似于数组,但是成员的值都是唯一的,没有重复的值。

const  常量名 = new Set();

包含的方法:

1.add(value):添加某个值,返回 Set 结构本身

2.delete(value):删除某个值,返回一个布尔值,表示删除是否成功

3.has(value):返回一个布尔值,表示该值是否为 Set 的成员

4.clear():清除所有成员,没有返回值

;