前言
- JS是html" title=前端>前端三件套之一,也是核心,本人将会更新JS基础、JS对象、DOM、BOM、ES6等知识点,这篇是ES6;
- 这篇文章是本人大一学习html" title=前端>前端的笔记;
- 欢迎点赞 + 收藏 + 关注,本人将会持续更新。
文章目录
- 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.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关键字
html">//如:创建一个class类
<script>javascript">
class Star {constructor(uname,age) {this.uname = uname;this.age = age;}
}//2.创建对象var ldh = new Star('ldh',18);
</script>
1.2.3、类中添加方法
语法:
html"><script>javascript">
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 {}
实例:
html"><script>javascript">
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前面。
如:
html"><script>javascript">
//父类
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、调用父类的普通函数
语法:
html"><script>javascript">calss Father {say() {return 'father';}}class Son extends Father {return super.say(); //注意}
</script>
1.5、三个注意点
- 在ES6类没有变量提升,所以必须先定义类,才通过类实例化对象
- 类里面的
共有属性和方法
一定要加this
使用 - 类里面的
this
指向:- constructor 里面的
this
指向指向对象 - 方法里面的
this
指向这个方法的调用
- constructor 里面的
1.6、面向对象tab案例
2、构造函数和原型
2.1、概述
类就是对象的模板,对象就是类的实例。
ES6之前,对象不是基于类创建的,而是用一种构建函数的特殊函数来定义和它们的特征。
- 创建对象有三种方法
- 字面量创建对象
- new Object()
- 自定义构造函数
html"><script>javascript">//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、静态和实例成员
html"><script>javascript">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
html"><script>javascript">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__指向相同
html"><script>javascript">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主要用于指向该对象哪一个构造函数
html"><script>javascript">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、原型链查找原则
- 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性
- 如果没有找到就查找原型_proto_ 指向的prototype对象
- 如果还没有就查找原型对象的模型(object的原型对象)
- 依次推直到 null
2.8、原型对象this指向
- 构造函数中
this
指向我们的实例对象 原型对象
里面放的是方法,这个方法里面的this指向的是这个方法的调用者,也就是这个实例对象
2.9、扩展内置对象
- 可以通过原型对象,对原来的内置对象进行扩展自定义的方法
- 如:
html"><script>javascript">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
:传递的其他参数
如:
html"><script>javascript">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,这样就可以实现子类继承父类的属性
html"><script>javascript">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、借用原型对象继承父类型方法
- 一般情况下,对象的方法都在构造函数的原型对象设置,通过构造函数无法继承父类方法
核心原理:
- 将子类所共享的方法提取出来,让子类
prototype 原型对象 = new 父类()
- 本质:子类原型对象等于实例化父类,因为父类实例化会另外开票空间
- 将子类的
consructor
重新指向子类的构造函数
html"><script>javascript">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、类的本质
- class本质还是function
- 类的所有方法都定义在类的
prototype
属性上 - 类创建的实例,里面也有
_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:数组对象本身
html"><script>javascript">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() 筛选数组
html"><script>javascript">array.filter(function(currentValue,index,arr)) {}
</script>
- filter( ) 方法创建一个新数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
- 返回一个新数组
html"><script>javascript">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
- 且注意:找到了满足条件的第一个元素,则终止循环,不在寻找
html"><script>javascript">var arr = [1,2,3,4,5];var flag = arr.some(function(value)) {return value === 2;}
</script>
4.2、字符串方法、
trim()
方法会从一个字符串的两端删除空白字符串trim
方法不会影响字符串本身,他返回的是一个新的字符串
html"><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
- 返回:一个由属性名组成的数组
- 返回:
html"><script>javascript">var obj = {name: 'pig',age: 18,sex: 'man'};var arr = Object.keys(obj);
</script>
4.3.2、Object.defineProperty()
Object.defineProperty()
定义对象中新属性或者修改原有得出属性
html">Object.defineProperty(obj,prop,descriptor)
- obj:目标对象
- prop:需定义或修改的属性的名字
- descriptor:目标属性所拥有的特性
html"><script>javascript">var obj = {id: 1,price: 5200}//定义新属性或者原来属性Object.defineProperty(obj,'price',{value: 100000,})Object.defineProperty(obj,'id',{//如果值为false,则不允许修改这个属性值,默认值也为falsewritable: false;})Object.defineProperty(obj,'id',{//如果值为false 则不允许遍历。默认值是falseenumerable: false})Object.defineProperty(obj,'id',{//如果值为false,则不允许删除这个属性,不允许修改,默认值为falseconfigurable: false})
</script>
第三个参数descriptor 说明:以对象新式{}书写
value:设置属性的值,默认为unvalue
writeable:值是否可以重写
enumerable:值是否可以列举
**configurable:**值是否可以被删除
5、函数进阶
5.1、函数的定义方式
-
函数声明方式function关键字(命名函数)
-
函数表达式
-
new Function()
-
html">var fn = new Function('参数一','参数二','函数体')
-
执行效率低
-
html"><script>javascript">//1.function fn() {};//2.var fun = function() {};//3.var f = new Function('a','b','console,log(a + b)');</script>
5.2、函数的调用方法
- 普通函数
- 对象的方法
- 构造函数
- 绑定事件函数
- 定时器函数
- 立即执行函数
html"><script>javascript">//1.function fn() P{
}//2.var o = {say: function() {}}o.say();//3.function Satr() {}new Star();//4.btn.onclick = function() {};//5.setInterval(function() {},1000);//6.(function() {})();
</script>
5.3、函数里面this的指向
this指向,是我们调用函数确定的(忘了可以通过代码)
5.4、改变函数内部this指向
- call() bind() apply()
5.4.1、call()方法
call()
如在继承中使用
同上
5.4.1、apply()方法
-
apply()
方法调用一个函数,简单理解为调用函数的方式 -
fun.apply(thisArg,[argsArray])
-
thisArg:在fun函数运行时指定的this值
-
argsArray:传递的值,必须包含在数组里面
-
返回值就函数的返回值
-
因此apply主要跟数组有关系,比如Math.max()求数组的最大值
html"><script>javascript">var o = {name: 'andy'};function fn(arr) {console.log(arr);}fn.apply(o,['pink']);//如:求最大值,最小值var arr = [1,2,3,4,55];var max = Math.max.apply(Math,arr);var min = Math.min.apply(Math,arr);
</script>
5.4.3、bind()方法 (重点)
bind()
方法不会调用函数。但是能改变函数内部this
指向fun.bind(thisArg,arg1,arg2,……)
- 只想要改变this指向,并不想调用这个函数的时候
html"><body><button>点击</button><script>javascript">var btn = querySelector('button');for(var i = 0;i < btn.length;i++) {btn[i].onclick = function() {this.disabled = true;setTimeout(function() {this.disabled = false;}.bind,2000)}}</script>
</body>
5.4.4、总结(call() \ apply() \ bind() )
不同点:
- call 和 apply 会调用函数,
- call 和 apply 传递的参数不一样,call 传递参数,apply 必须数组形式
- bind 不会调用函数
主要运用场景
- call 经常做继承
- apply 经常和数组有关,如数组最大值和最小值
- bind 不调用函数,如:改变定时器内部this指向
6、严格模式
6.1、开启严格模式
- 严格模式可以运用到
整个脚本
或个别函数
中 - 因此在使用时,我们可以将严格模式分别为
为脚本开启严格模式
和为函数开启严格模式两种情况
6.1.2、为脚本开启严格模式
- 为整个脚本文件开启严格模式,需要
在所有语句之前放一个特定语句
'use strict'
或"use strict"
html"><script>javascript">//最好用立即执行函数封装一个严格模式(function () {'use strict';})();//或者在头上直接声明'use strict';
</script>
6.1.2、为函数开启严格模式
html"><script>javascript">function fun() {'use strict';}
</script>
7、严格模式中的变化
- 严格模式对js的语法和行为,都做了一些改变
7.1、变量规定
- 在正常模式中,如果一个变量没有声明就赋值,默认为全局变量
- 但是在严格模式下,这种方式静止使用
- 严禁删除已经声明的变量,如:使用
delete
语法是错误的
7.2、严格模式下this指向问题
- 以前在 全局作用域中的 this指向window对象
- 严格模式下全局作用域中函数中this是undefined
- 以前构造函数时不加new也可以调用,当普通函数,this指向全局对象
- 在严格模式下,如果构造函数不加new调用,this指向的是undefine,且不能赋值
- new实例化构造函数指向创建的创建的对象实例
- 定时器this还是指向window
- 事件、对象还是指向调用者
7.3、函数变化
- 函数不能有重名函数
- 函数声明必须在顶层,不允许在非函数的代码块内声明函数(如if 语句,for语句中)。
8、高阶函数
- 高阶函数是对其他函数进行操作的函数,它接受函数作为参数或者将函数作为返回值输出
html"><script>javascript">//接收函数作为参数function fn(a,b,callback) {console.log(a+b);callback&&callback();}fn(5,6,function() {console.log("end");})//将函数作为返回值function fn() {return function(){}}
</script>
9、闭包
9.1、变量作用域
变量作用域分为两种:全局变量和局部变量
- 函数内部可以使用全局变量
- 函数外部不可以使用局部变量
- 当函数执行完毕,本作用域的局部变量会销毁
9.2、什么是闭包
简单理解:一个作用域可以访问另一个函数内部的局部变量
html"><script>javascript">//闭包:closurefunction fn1() {var num = 10;function fn2() {console.log(num); //10}}fn1();//调用fn2函数var f = fn1();f();
</script>
9.3、在chrome中调试闭包
9.4、闭包作用
- 延伸变量的作用范围,一般结合立即执行函数一起执行。
html"><script>javascript">function fn1() {var num = 10;function fn2() {console.log(num); //10}}var f = fn1();f();
</script>
9.5、闭包练习
9.5.1、点击li输出索引号
html"><body><ul class="nav"><li>榴莲</li><li>臭豆腐</li><li>鲱鱼罐头</li><li>大猪蹄子</li></ul><script>javascript">//页面元素操作 BOM DOM//1.利用动态添加属性方法var lis = document.querySelector('.nav').querySelectorAll('li');for(var i = 0; i < lis.length;i++) {lis[i].index = i;lis[i].onclick = function() {console.log(this.index);}}//2.利用闭包的方式得到当前小li的索引号for(var i = 0;i < lis.length;i++) {(function(i) {lis[i].onclick = function() {console.log(i);}})(i);}</script>
</body>
9.5.2、定时器中的闭包
html"><body><ul class="nav"><li>榴莲</li><li>臭豆腐</li><li>鲱鱼罐头</li><li>大猪蹄子</li></ul>// 3秒之后,打印所有li元素内容var lis = document.querySelector('.nav').querySelectorAll('li');for(var i = 0;i < lis.length;i++) {(function(i) {setTimeout(function() { console.log(lis[i].innerHTML);} , 3000)})();}
</body>