一、JavaScript的组成
2. BOM:浏览器对象模型(操作浏览器)—- 核心对象 window
3. DOM:文档对象模型(操作html文档)—- 核心对象document
二、ECMAScript
1. ECMAScript5:脚步语言。不需要独立的编译器,通过浏览器加载运行。实现用户和页面的交互
2. ECMAScript6:是JavaScript的下一代语法标准,于2015年6月发布。是JavaScript正式成为企业级的开发语言
ECMAScript是一个语法规范,JavaScript是该语法规范的实现
三、ES6的语法
1. let 和const
(1)let:用来声明块级变量。var声明的变量会出现作用域的提升(会出现变量的污染)
(2)const:声明的常量必须要初始化
(3)const声明的对象:常对象
1)可以修改对象的属性值,但是不能修改对象本身
const obj = {
name:'张三',
age:25
}
obj.name = '李四' //正确的:修改对象的属性
obj = {} // 错误的:不能改变对象
2)冻结对象:不能修改对象的属性。使用Object.freeze(对象名)
const obj = {
name:'李四',
age: 25
}
console.log(obj)
Object.freeze(obj) //冻结对象obj,就不能修改obj的属性
obj.name = '王五'
console.log(obj)
3)冻结嵌套的对象
hasOwnProperty(key)函数:判断key是否是对象的属性,若是返回true,不是返回false
遍历对象的属性:for…in
for(let k in obj){ }
const p = {
name:'李四',
age: 25,
family:{
father:'李世民',
mother:'长孙皇后'
}
}
//定义一个冻结函数
function fun(obj){ //函数的参数是对象
//1.冻结对象:参数接收的对象
Object.freeze(obj)
//2.使用for...in循环遍历对象的属性
for(let key in obj){ //key = 'mother'
//2.1 hasOwnProperty用来判断对象是否包含给定的属性。typeyof用来判断数据类型
if(obj.hasOwnProperty(key) && typeof obj[key] === 'object'){// obj['mother'] -- string
fun(obj[key])
}
}
}
fun(p)
p.family.father = '李建成'
console.log(p)
4)构造函数
a. 作用:初始化对象(是对象的模型),所有的对象都是用这个模型造出来的
b. this:指向由构造函数创建的对象(代表当前对象)
c. 对象:是属性和行为的结合体
属性:是对象的静态特征(成员变量)
行为:是对象的动态特征(函数 / 方法)
<script>
/*需求:定义构造函数Student,属性分别是:id、name、html、css、JavaScript
(1)创建5个Student对象,把这5个对象存入数组
(2)找出总成绩最高的对象
(3)根据javascript成绩对数组进行降序排序
*/
//1.定义构造函数
function Student(id,name,html,css,javascript){
//1.1 定义属性:this后的是属性
this.id = id
this.name = name
this.html = html
this.css = css
this.javascript = javascript
//1.2 定义方法:求对象的总成绩
this.total = function(){
return this.html + this.css + this.javascript
}
}
//2.创建对象,然后将对象存入数组
let s1 = new Student(101,'贾宝玉',78,85,95)
let s2 = new Student(102,'贾元春',65,88,98)
let s3 = new Student(103,'贾探春',75,65,88)
let s4 = new Student(104,'贾迎春',90,80,92)
let s5 = new Student(105,'贾惜春',72,78,86)
let arr = [s1,s2,s3,s4,s5] //arr数组称为对象数组
console.log(arr)
//3. 找总成绩最高的
let max = arr[0] //假定数组中第一个对象的总成绩最高
for(let i=1;i<arr.length;i++){
if(arr[i].total() > max.total()){
max = arr[i]
}
}
console.log("总成绩最高的是:",max)
//4.按JavaScript的成绩进行降序排序
for(let i=0;i<arr.length;i++){
for(let j=0;j<arr.length-1;j++){
if(arr[j].javascript < arr[j+1].javascript){
let t = arr[j]
arr[j] = arr[j+1]
arr[j+1] = t
}
}
}
console.log(arr)
</script>
四 、ES6的新特性
1. 临时死区:用let和const声明的变量,放在‘临时死区’,使用let声明的变量、const声明的常量的作用域不会被提升
let arr=[]
for(var i=0;i<5;i++){ //var定义的i是全局的,若将var改成let,则输出0 1 2 3 4
arr.push(function(){ //arr是一个函数数组:数组的每个单元都是函数
console.log(i);
})
}
arr.forEach(function(item){ //item是函数:输出5个5
item();
})
3. 解构赋值:Rest运算符:”…”
(1)当迭代器使用:会按顺序遍历容器中的元素
function fun(x,y,z){
console.log(x,y,z)
}
let arr = [11,22,33]
fun(...arr) //'...'运算符的作用是一个迭代器:依次遍历数组中的元素
(2)替代函数的内置属性arguments
function fun(...args){
console.log(args)
}
let arr = [11,22,33]
fun(arr)
(3)通过解构赋值可以简化变量的赋值
let arr = [11,22,33]
let [a,b,c] = arr
console.log(a)
(4)通过”…”把特定的元素放在变量里
let [a,...arr] = [11,22,33] //将11赋给a,将22,33赋给arr,arr就是一个数组
console.log(a)
console.log(arr)
(5)通过解构来交换变量的值
let a = 10
let b = 20; //必须要以分号结尾
[a,b] = [b,a]
console.log(a,b)
4. 对象的解构
(1)将对象的属性解构出来赋给变量
let obj = {
id:1001,
userName:'关羽',
sex:'男'
}
let { id,userName,sex } = obj //变量名必须和对象的属性名相同
console.log('编号:',id)
console.log('用户名:',userName)
console.log('性别:',sex)
(2)解构多层对象
let obj = {
id:1001,
userName:'关羽',
sex:'男',
score:{
html: 98,
css:95,
js: 85
}
}
let { id,userName,sex,score:{html,css,js} } = obj //变量名必须和对象的属性名相同
console.log('编号:',id)
console.log('用户名:',userName)
console.log('性别:',sex)
console.log('css的成绩:',css)
(3)在解构时可以给变量取别名
let obj = {
id:1001,
userName:'关羽',
sex:'男',
score:{
html: 98,
css:95,
js: 85
}
}
let { id:userId,userName:name } = obj //userId是id的别名,name是userName的别名
console.log('编号:',userId)
console.log('用户名:',name)
console.log('性别:',sex)
5. 模板字符串:使用反引号“和${ 变量名 } 将字符串常量和变量写在一个串里。就不需要使用’+’进行字符串的拼接
(1)ES5的数据类型:number、string、boolean、bigint、null、undefined、object
(2)ES6新增的Symbol:表示一个唯一的值
1)直接创建:let 变量名 = Symbol
<script>
let s1 = Symbol
let s2 = Symbol
console.log(s1 == s2)//true
</script>
2)间接创建:传字符串 let 变量名 = Symbol(字符串)
<script>
let a1 = Symbol('abc')
let a2 = Symbol('abc')
console.log(a1 === a2)//false
let obj = {
a1:'asd',
a2:'aqw'
}
</script>
7. Set集合:是一种数据结构,里面不能存放重复的值。可以用于数组去重、字符串去重
(1)创建方式:
1)使用new运算符:let 变量 = new Set()
<script>
let s1 = new Set()//创建一个空集合
console.log(s1)
</script>
2)通过数组来创建:let 变量名 = new Set( [1,2,3,5,6] ) ,去除重复的元素
<script>
let arr = [1,2,34,6,5,4,3,2,6,4]
let s2 = new Set(arr)
console.log(s2)
</script>
(2)常用的方法:
1)add(val):向集合中添加元素
2)delete(val):删除集合中的元素。删除成功返回true,删除失败返回false
3)has(val):判断val在集合中是否存在,若存在返回true,不存在返回false
4)clear():清空集合,没有返回中
5)values():获取的是集合中所有value
6)keys():获取集合中的key
let s1 = new Set()//创建一个空集合
console.log(s1)
let arr = [1, 2, 3, 2, 0, 3, 5]
let s2 = new Set(arr)
console.log(s2)
let temp = s1.add('table')
console.log(typeof temp)
s1.add(123).add(456).add('abc')
// console.log(s1)//集合
// console.log(...s1)//解构
// console.log([...s1])//将集合转换成数组
let flag = s1.delete(123)
console.log(flag)
console.log(...s1)
let f = s1.has('table')
console.log(f)
s1.clear()
console.log(s1)
let t =s1.values()
console.log('values:',t)
let k =s1.keys()
console.log('keys:',k)
强调:Set集合也是key-value格式,它的key和value是相同的
(3)属性:size 存放的是集合中元素的个数
(4)遍历方法:
1)for … of
for(let i of s1.keys()){
console.log(i);
}
console.log('Size:',s1.size);
2)forEach
s1.forEach(function(value,key){
console.log(value+'--------'+key)
})
(5)集合运算
1)并集
let setA = new Set([4, 5, 6])
let setB = new Set([5, 6, 7])
//实现setA与setB的并集
let bj = new Set([...setA, ...setB])
console.log(bj)
2)交集
<script>
let set1 = new Set([12,3,4,2])
let set2 = new Set([2,3,45])
// 2.实现set1与set2的交集:通过过滤器实现
// [...set1]解构集合set1,将其转换成数组
let t = [...set1]
// console.log(t)
// 对t进行过滤:使用filter函数
let t1 = t.filter(function(item){//依次从t中取出元素传递给item,在函数体内设置筛选条件,将满足条件的元素赋给t1
return set2.has(item)//将满足条件的item返回
// 上下等价
if (set2.has(item)) {
return item
}
})
console.log(t1)
</script>
3)差集
let setA = new Set([4, 5, 6]);
let setB = new Set([5, 6, 7]);
/*2.实现setA与setB的交际:通过过滤器实现
[...setA]:解构集合setA,将其转换为数组
*/
let arr = [...setA]; //解构集合setA,将其转换为数组
//对arr进行过滤:使用filter函数
//第一种
let temp = arr.filter(function (item) { //依次从arr中取出元素传递给item,在函数体内设置筛选的条件,将满足条件的元素返回给temp
// return setB.has(item); //将满足条件的item返回(简写)
if(setB.has(item) == false){
return item
}
})
console.log(temp);
//第二种
let t = [...setA].filter(function (item) {
return setB.has(item);
})
console.log(t);
问题1:创建Set集合时为什么用new运算符?
Set是一个构造函数,凡是用构造函数创建对象时都要用new
底层代码规定的
8. WeakSet集合:只是一个对象集合。即集合中只能存放对象。它支持 add,has 和 delete 方法
<script>
let obj1 = {
name:'cc',
age:18
}
let ws = new WeakSet([{'a':23}])
ws.add(obj1)
console.log(ws)
console.log(ws.has())
ws.delete(obj1)
console.log(ws)
</script>
五、Map集合
1. 数据的存放格式:采用 key-value(键值对) 的方式进行存放。采用这种方式存放数据的有
(1)对象:属性对应的是key(键),属性值对应的是value(值)
let obj1 = {
name:'kk',
age:14
}
(2)JSON:是常用的一种前后台数据交换的格式
2. Map的定义:Map是一种数据结构(Hash结构),在ES6中是Map一种存放许多键值对的有序列表
(1)属性:size —- 存放的是Map中的元素个数
(2)方法
1)Map():构造方法。用来创建Map对象,不带参数表示创建空的Map,即size属性值为0
let m1 = new Map()//构造方法,创建Map对象
console.log('size:',m1.size)
2)set(key,value):向Map中添加数据
let m1 = new Map()//构造方法,创建Map对象
m1.set('name','张三')//set,向Map中添加数据
m1.set('USA','美国')
m1.set('CHINA','中国')
m1.set('INA','印度')
3)get(key):获取键为key的value
let m1 = new Map()//构造方法,创建Map对象
m1.set('name','张三')//set,向Map中添加数据
m1.set('USA','美国')
m1.set('CHINA','中国')
m1.set('INA','印度')
console.log(m1.get("name"));
4)has(key):判断Map中是否存在key
let m1 = new Map()//构造方法,创建Map对象
m1.set('name','张三')//set,向Map中添加数据
m1.set('USA','美国')
m1.set('CHINA','中国')
m1.set('INA','印度')
console.log(m1.has("INA"));
5)delete(key):删除key
console.log(m1.delete('US'))
6)clear():清空Map
7)keys():返回Map中的所有key
console.log(m1.keys())
课堂练习1:以“key” <===> “value”,显示一个Map
(1)Map中的key不能重复,但是value可以重复
(2)keys()返回的是Map中所有key集合 —— keys()返回的集合类型是Set
(3)在Map中通过key可以得到对应的value,反之则不行
8)values():返回Map中的所有value
for(let a of map.values()){
console.log(a)
}
9)entries():可以获取Map的所有成员(即所有的key-value)
for (const temp of map.entries()) {//.entries()可以不写
console.log(temp)
}
// or
for (const [key, value] of map.entries()) {
console.log(`${key}:${value}`)
}
10)forEach循环遍历
map.forEach(function (value, key) {//第一个参数是value,第二个是key
console.log(`${key}:${value}`)
})
练习 Map数组(数组的每个单元都是一个key-value)的使用
let m1 = new Map()
m1.set('XA','西安')
m1.set('XY','咸阳')
let m2 = new Map()
m2.set('K1','重庆')
m2.set('K2','成都')
let m3 = new Map()
let arr = [m1,m2,m3] //arr是Map数组
console.log(arr)
//输出'西安'
console.log(arr[0].get('XA'))
4. Map转换为数组
(1)解构整个Map
let m4 = new Map([
[‘one’,’北京’],
[‘two’,’上海’],
[‘three’,’深圳’]
])
let arr = [...m4.entries()] //将m4转换成数组.arr本质是3行2列的二维数组
console.log(arr)
(2)解构keys()
let a1 = [...m4.keys()] //将Map的所有key转换成数组
console.log(a1)
(3)解构values()
let a2 = [...m4.values()]//将Map的所有value转换成数组
console.log(a2)
六、函数
(1)通过function关键字定义函数
function 函数名([参数]){ }
(2)函数表达式
let 变量 = function([参数]){ }
注意:
(1)形参和实参的区别
(2)函数的返回值:return语句来实现
(1)函数形参的默认值
function fun(a,b,c=45){ //形参c的默认值为45,如果调用函数时没有给c传递参数值,则使用默认值
console.log('a=',a)
console.log('b=',b)
console.log('c=',c)
}
let a = 10,b = 20,c = 30
fun(a,b)
(2)箭头函数:在定义函数时使用“=>”符号。在定义回调函数(高阶函数)、函数表达式时使用。可以简化代码
<script>
//1.函数没有参数,函数体语句只有一条
let fun = ()=> "张三"
// let du =()=>'dd'
let du =()=>{return 'dd'}
//大括号省略,默认含有返回的功能
console.log(du())
//2.函数带有一个参数,可以省略‘()’
let f2 = args =>{
console.log(args)
}
f2(1024)//函数调用,将1024传递给形参args
//3.箭头函数带有多个参数
let f3=(arg1,arg2)=>arg1+arg2
//等价于
// let f3 = (arg1,arg2)=>{return(arg1+arg2)}
console.log(f3)
//4.函数体只有一条语句,函数返回对象:必须用'()'将对象包起来
let f4 = ()=>({
name:'张三',
age:25
})
console.log(f4())
window.id='宝塔镇河妖'
//5.箭头函数中this的绑定问题
let obj = {
id:'s101',
f5:function(){
console.log(this.id)//this代表obj
},
f6:()=>{
console.log(this.id)//输出undefined,因为箭头函数没有绑定this,这时this指向离它最近的上层对象
}
}
obj.f5()
obj.f6()
//6.箭头函数没有内置的arguments
let pt = ()=>{
console.log(arguments)//Uncaught ReferenceError: arguments is not defined
}
pt(12,23,34)
</script>
七、类
1. 面向对象:是一种开发思想,一切皆为对象。对象是属性和行为的结合体
2. 面向过程:也是一种开发思想。开发中的每个细节,开发者都要考虑到。
4. ES5中实现类的功能:构造函数,在构造函数中封装了属性和方法。缺陷是构造函数和普通函数的定义方式是一样的
class 类名{
属性
行为
}
class 是关键字,专门用来定义类。
<script>
//1.用class定义Student类
class Student{
constructor(id,name,sex){//构造函数.this后面的id,name,sex是属性
this.id = id
this.name = name
this.sex = sex
}
display(){
console.log('学号:',this.id)
console.log('姓名:',this.name)
console.log('性别:',this.sex)
}
}
//2.使用Student类创建对象:创建对象时不能显式地使用constructor,必须用类名创建,默认调用类的构造即constructor函数
let s1 = new Student(101,'令狐冲','男')
let s2 = new Student(102,'郭靖','男')
let s3 = new Student(103,'黄蓉','女')
//3.使用对象
s1.display()
console.log('----------------------')
s2.display()
console.log('----------------------')
s3.display()
</script>
6. ES6中支持getter/setter来获取属性值、设置属性值
(1)定义get方法、set方法的目的是:用于隐藏对象的属性名
(2)在使用get方法、set方法方法时不用带’()’
<script>
class Account{
constructor(id,pwd){
this._id = id//加'_'的属性,称为私有属性(是语义上的区分)
this._pwd = pwd
}
// 1.定义get方法:获取属性的值
get id(){
return this._id
}
get pwd(){
return this._pwd
}
// 2.定义set方法:设置属性值
set id(value){
this._id = value
}
set pwd(value){
this._pwd = value
}
}
let a1 = new Account('1001','123456')
console.log('账号:',a1.id)//a1.id实际调用的是id()方法
console.log('密码:',a1.pwd)//a1.pwd实际调用的是pwd()方法,因为pwd()方法前有get,因此调用时不用带'()'
console.log('--------------------------')
a1.id = '1002'//实际调用的是set id(value)方法
a1.pwd = '111111'//实际调用的是set pwd(value)方法
console.log('账号:',a1.id)
console.log('密码:',a1.pwd)
</script>
7. 类的属性和方法(函数):类可以有属性也没有没有属性,可以有方法也可以没有方法
8. 类的属性是放在构造方法中初始化的,若类没有属性,可以不显式定义构造方法,此时,系统会自动生成一个无参的空的构造方法
八、类的继承
(1)父类(基类):可以派生子类的类
(2)子类(派生类):由父类派生而来的类
2. 继承的好处
在父类中定义的属性和方法,子类继承后就可以直接使用。
(1)封装性:对象是属性和行为的封装体 —- 数据安全
(2)继承性:子类可以继承父类的属性和方法 —- 代码复用
(3)多态性:同一个消息传递给不同对象,出现的效果不同 —- 应用灵活、可以适应不同的需求
(1)ES5中继承的实现:没有类的概念
1)构造函数:构造函数名就是类名,在ES5中类的继承实际就是构造函数的继承
2)实现:通过call、apply、bind函数来实现构造函数的继承
//1.定义构造函数:基类
function Fatcher(name){
this.name = name
this.age = 45
}
//2.定义构造函数:子类
function Son(name){
/* this代表是上层对象(window),name参数传递个Father构造函数。
等于在Son函数中调用了Father函数:Son就具有了name和age属性(相当于从Father继承了name和age)
*/
Fatcher.call(this,name) //函数劫持,在Son中通过call调用Father构造函数,将参数name传递给Father构造函数
this.height = '178cm' //height是Son自己的属性
this.show= function(){
console.log('姓名:',this.name)
console.log('年龄:',this.age)
console.log('身高:',this.height)
}
}
let son = new Son('赵四')
son.show()
(2)ES6中的继承:通过关键字extends实现
//1.定义父类Fatcher
class Fatcher{
constructor(name,age){
this.name = name
this.age = age
}
fun(){
console.log('我是父类中的方法......')
}
}
//2.定义子类Son,继承自Father类
class Son extends Fatcher{
constructor(name,age){
super(name,age); //调用父类的构造函数
}
hobby(){
console.log('我喜欢篮球')
}
show(){
console.log('姓名:',this.name)
console.log('年龄:',this.age)
}
}
let s1 = new Son('张三',25)
s1.hobby()
s1.show()
s1.fun()
A、super:指向父类。super([参数])表示调用父类的构造函数
B、如果在子类的构造函数中调用父类的构造函数,那么super()必须作为子类构造函数中的第一条语句
在执行子类的构造函数之前必须先执行父类的构造函数(先有父,后有子)
C、方法覆盖(Overwrite):在继承过程中,若父类的某个方法与子类的某个方法同名,则子类方法覆盖父类的同名方法
D、在子类的方法中可以使用super调用父类中的某个方法
E、不允许多继承,只能单继承
多继承:类的直接父类有多个
单继承:类的直接父类只有一个父类
5. 类继承过程中的向上转型
子类对象的类型一定是父类的类型,父类对象的类型不能是子类的类型
1)typeof:用于判断变量的数据类型(基本数据类型)
typeof 变量名 == ‘数据类型’
2)instanceof:用于判断变量的数据类型(类类型)
对象名 instanceof 类名
判断”对象”是否是给定的类的对象
class Sports{
constructor(){}
play(){}
}
class FootBall extends Sports{
constructor(){
super()
}
play(){
console.log('足球是用脚踢的......')
}
}
class Bascketball extends Sports{
constructor(){
super()
}
play(){
console.log('篮球是用手打的......')
}
}
function howToPlay(sp){
sp.play()
}
let sport = new Sports() //sport是基类的对象
let foot = new FootBall()
let flag = (foot instanceof Sports) //子类对象foot是父类Sports类型 --- 向上转型
console.log("flag= ",flag) //flag = true
let flag = (sp instanceof FootBall) //父类对象sp不能是子类FootBall类型 --- 不能向下转型
console.log("flag= ",flag) //flag = false
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/79774.html