(function(){ //匿名函数自调用
var a = 3
console.log(a+3) //6
})()
var a = 4
console.log(a) //4
(function(){
var a = 1
function test(){
console.log(++a)
}
window.$ = function(){
return{
test:test
}
}
})()
$().test() //2
判断:
typeof:
可以区别:数值、字符串、布尔值、undefined、function
不能区别:null与对象,一般对象和数组
instanceid
专门用来判断对象数据的类型:
Object,Array与Function
===
可以判断:undefined和null
instanceof是如何判断的?
表达式:A instanceof B 实例对象 构造函数
实例对象的隐式原型等于构造函数的显式原型
执行上下文
1、先执行变量提升,再执行函数提升
内存、数据、变量
内存是用来存储数据的空间
变量是内存的标识
1.关于引用变量赋值的问题:
n个引用变量指向同一个对象,通过一个变量修改对象内部数据,其它所有变量看到的是修改之后的数据
两个引用变量指向同一个对象,让其中一个引用变量指向另一个对象,另一引用变量依然指向前一个对象
2.在js调用函数时传递变量参数时,是值传递还是引用传递
3.JS引擎如何管理内存?
①内存生命周期
分配小内存空间,得到它的使用权
存储数据,可以反复进行操作
释放小内存空间
②释放内存
局部变量:函数执行自动释放
对象:成为垃圾对象==>垃圾回收器回收
对象
如何确定this的值?
test():window
p.test: p
new test(): 新创建的对象
p.call(obj):obj
1.什么是对象
多个数据的封装体(集合体)
用来保存多个数据的容器
一个对象代表现实中的一个事物
2.为什么要用对象
统一管理多个数据
3.对象的组成
属性:代表现实事物的状态数据
由属性名(字符串)和属性值(任意值)组成
方法:代表现实事物的行为数据、一种特别的属性(属性值是函数)
4.如何访问对象内部数据
.属性名:编码简单,有时不能用
[‘属性名’]:编码简单,能通用
什么时候必须使用[‘属性名’]的方式?
①.属性名包含特殊字符:- 空格
②.属性名不确定
===========================
1.什么是函数?
具有特定功能的n条语句的封装体
只有函数是可以执行的,其他类型的数据不能执行
2.为什么要用函数?
提高代码复用
便于阅读交流
3.如何定义函数
函数声明
表达式
4.如何调用(执行)函数
直接调用test()
通过对象调用obj.test()
new调用 new test()
临时让test成为obj的方法进行调用
test.call/apply(obj)
var obj5 = {}
function test(){
this.xxx = "你好"
}
//obj5.test() 不能直接调用,根本就没有此方法
test.call(obj5)
//可以让一个函数成为指定任意对象的方法进行调用
console.log(obj5.xxx) //你好
=======================
什么函数才是回调函数?
1)你定义的
2)你没有调用
3)但最终执行了
常见的回调函数?
dom事件回调函数
定时器回调函数
ajax请求回调函数
生命周期回调函数
===============
IIFE(Immediately-Invoked Function Expression立即调用函数表达式)
别名:匿名函数自调用
作用
隐藏调用
隐藏内部实现
不会污染外部(全局)命名空间
用它来编码js模块
=================
1.this是什么?
任何函数本质上都是通过某个对象来调用的,如果没有直接指定就是window
所有函数内部都有一个变量this
它的值是调用函数的当前对象
如何确定this的值?
test():window
p.test: p
new test(): 新创建的对象
p.call(obj):obj
回调函数:异步执行
js单线程 也就是说只能有一个线程更新操作界面
箭头函数适合与this无关的问题,定时器,数组的方法回调
不适合与this相关的回调 比如dom事件回调、对象的方法
rest参数
for。。。in 键值
for。。。of键名
函数的prototype属性
1、每个函数都有一个protopype属性,它默认指向一个Object空对象(即称为:原型对象)
原型对象中有一个constructor,它指向函数对象
console.log(fun.prototype.constructor=fun)
2、给原型对象添加属性(一般是方法)=>实例对象可以访问
========
显式原型与隐式原型
1.每个函数function都有一个prototype,即显式原型(属性)
2.每个实例对象都有一个__proto__,可称为隐式原型
3.对象的隐式原型的值为其对应构造函数的显式原型的值
总结:
函数的prototype属性:在定义函数时自动添加的,默认值是一个空Object对象
对象的_proto_属性:创建对象时自动添加的,默认值为构造函数的prototype属性值
程序员能直接操作显式原型,但不能直接操作隐式原型(ES6之前)
1.读取对象的属性值时:会自动到原型链中查找
2.设置对象的属性值时:不会查找原型链,如果当前对象中没有此属性,直接添加此属性并设置其值
3.方法一般定义在原型中,属性一般通过构造函数定义在对象本身上
变量声明与提升
通过var 定义(声明)的变量,在语句之前就可以访问到
值:undefined
函数声明提升
通过function声明的函数,在之前就可以直接调用
值:函数定义(对象)
面试题:输出undefined
var a = 3
function fn(){
console.log(a)
var a = 4
}
fn()//undefined
=======================
console.log(b) //undefined 变量提升
fn2()//fn2() 函数提升 可调用
var b = 3
function fn2(){
console.log('fn2()')
}
=======================
1.代码分类(位置)
全局代码
函数代码
2.全局执行上下文
在执行全局代码前将window确定为全局执行上下文
对全局数据进行预处理
var 定义的全局变量==>undefined,添加为window的属性
function声明的全局函数==>赋值(fun),添加为window的方法
this==>赋值(window)
开始执行全局代码
3.函数执行上下文
在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象(虚拟的,存在于栈中)
对局部数据进行预处理
形参变量==>赋值(实参)>添加为执行上下文的属性
arguments>赋值(实参列表),添加为执行上下文的属性
this==>赋值(调用函数的对象)
开始执行函数体代码
var a = 10
var bar = function(x){
var b = 5
foo(x + b)
}
var foo = function(y){
var c = 5
console.log(a + c + y)//30
}
bar(10)
// this是静态的,this始终指向函数声明时所在作用域下的this的值
function getName(){
console.log(this.name)
}
let getName2 = ()=>{
console.log(this.name)
}
// 设置window对象的name属性
window.name = '南风知我意'
const school = {
name:"ATGUIGU"
}
//普通调用方法
getName()//南风知我意
getName2()//南风知我意
// call方法调用
getName.call(school)//ATGUIGU
getName2.call(school)//南风知我意
// 不能作为构造实例化对象
let Person = (name,age)=>{
this.name = name;
this.age = age;
}
// let Person = function(name,age){
// this.name = name;
// this.age = age;
// }
let me = new Person('xiaomi',18);
console.log(me)
//demo5.html:36 Uncaught TypeError: Person is //not a constructor
//at demo5.html:36:13
箭头函数的简写
1)省略小括号,当形参有且只有一个的时候
let add = (n)=>{
return n+n
}
console.log(add(9))//18
==========
let add = n=>{
return n+n
}
console.log(add(9))//18
===========
let add = n=>n+n
console.log(add(9))//18
2)省略花括号,当代码体只有一条语句的时候,此时return必须省略、而且语句的执行结果就是函数的返回值
let pow = (n)=>n*n;
console.log(pow(8))//64
箭头函数适合与this无关的回调,定时器,数组的方法回调
箭头函数不适合与this有关的回调,事件回调,对象的方法
{
name:'尚硅谷',
getName:()=>{
this.name
}
}
与结构赋值结合
function connect({host="127.0.0.1",username,password,port}){
console.log(host)
console.log(username)
console.log(password)
console.log(port)
}
connect({
host:'atguigu.com',//这里不传值的话就用上边默认值,传的话就用传的值
username:'root',
password:'root',
port:3306
})
ES6引入rest参数,用于获取函数的实参,用来代替arguments
ES5获取实参的方式
function date(){
console.log(arguments)
}
date('黎明','郭富城','刘德华','张学友');
//Arguments(4) ['黎明', '郭富城', '刘德华', '张学友', callee: ƒ, Symbol(Symbol.iterator): ƒ]
//0: "黎明"
//1: "郭富城"
//2: "刘德华"
//3: "张学友"
=============
//rest参数
function date(...args){
console.log(args)
}
date('黎明','郭富城','刘德华','张学友');
//['黎明', '郭富城', '刘德华', '张学友']
数组的合并
const cat = ['橘猫','橘橘猫']
const dog = ['拉布拉多','金毛']
// const CatDog = cat.concat(dog)
const CatDog = [...cat,...dog]
console.log(CatDog)
数组的克隆
const sanzhihua = ['E','G','M'];
const sanyecao = [...sanzhihua]
console.log(sanyecao)
将伪数组转为真正的数组
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
const divs = document.querySelectorAll('div')
const divArr = [...divs]
console.log(divArr)
//[div, div, div, div, div]
生成器其实就是一个特殊的函数
异步编程 纯回调函数 node fs ajax mongodb
函数代码的分隔符
function * gen(){
console.log(111);
yield '一直没有耳朵'
console.log(222)
yield '一直没有尾巴'
console.log(333)
yield '真奇怪'
console.log(444)
}
let iterator = gen();
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
// iterator.next()//111
// iterator.next()//222
// iterator.next()//333
// iterator.next()//444
// 遍历
for(let v of gen()){
console.log(v)
}
111
一直没有耳朵
222
一直没有尾巴
333
真奇怪
444
========================
生成器函数参数
function * cat6(arg){
console.log(arg);//AAA
let one = yield 111;
console.log(one);//BBB
let two = yield 222;
console.log(two);//CCC
yield 333;
}
let iterator2 = cat6('AAA')
console.log(iterator2.next()) //111
// next方法可以传入实参
console.log(iterator2.next('BBB'))
console.log(iterator2.next('CCC'))
生成器函数实例
//一秒后输出111两秒后输出222,三秒后输出333
//回调地狱
setTimeout(()=>{
console.log(111)
setTimeout(()=>{
console.log(222)
setTimeout(()=>{
console.log(333)
},3000)
},2000)
},1000)
========================
//生成器
function one(){
setTimeout(()=>{
console.log(111)
iterator3.next()
},1000)
}
function two(){
setTimeout(()=>{
console.log(222)
iterator3.next()
},2000)
}
function three(){
setTimeout(()=>{
console.log(333)
iterator3.next()
},3000)
}
function * gen6(){
yield one();
yield two();
yield three();
}
let iterator3 = gen6()
console.log(iterator3.next())
Set集合实践
let arr = [1,2,3,4,2,3,5]
// set数组去重
// let result = [...new Set(arr)]
// console.log(result)//1,2,3,4,5
// 2.交集
let arr2 = [1,2,4,4,6]
let result = [...new Set(arr)].filter(item=>{
let s2 = new Set(arr2)
if(s2.has(item)){
return true
}else{
return false
}
})
let result8 = [...new Set(arr)].filter(item=>new Set(arr2).has(item));
console.log(result8)
// 并集
let union = [...new Set([...arr,...arr2])];
console.log(union)//1,2,3,4,5,6
// 差集
let diff = [...new Set(arr)].filter(item=>!(new Set(arr2).has(item)));
console.log(diff)//3,5
Map
let m = new Map()
m.set('name','橘猫')
m.set('age',3)
m.set('change',function(){
console.log('橘猫巨可爱')
});
let key = {
school : 'ATGUIGU'
};
m.set(key,['北京','上海','深圳']);
console.log(m)
console.log(m.size)//4
console.log(m.has('name'))//true
console.log(m.get('age'))//3
// 遍历
for(let v of m){
console.log(v)
}
size 返回Map元素个数
set 添加一个新元素,返回当前Map
get 返回键名对象的键值
has 检查Map中是否包含某个元素,返回boolean值
clear清除集合,返回undefined
class类
1.class声明类
2.constructor定义构造函数初始化
3.extends继承父类
4.super调用父级构造函数
5.static定义静态方法和属性
6.父类方法可以重写
function Phone(brand,price){
this.brand = brand
this.price = price
}
//添加方法
Phone.prototype.call = function(){
console.log('我可以打电话')
}
// 实例化对象
let Huawei = new Phone('华为',5999)
Huawei.call()
console.log(Huawei)
=========
class Shouji{
// 构造方法,名字不能修改
constructor(brand,price){
this.brand = brand
this.price = price
}
// 方法必须使用该语法,不能使用ES5的对象完整形式
call(){
console.log('我可以打电话')
}
}
let onePlus = new Shouji("1+",1999);
console.log(onePlus)
=====================
//static标注的属性和方法 不能作为实例对象的属性和方法
class Phone1{
// 静态属性
static name = '手机';
static change(){
console.log("我可以改变世界");
}
}
let nokia = new Phone1();
console.log(nokia.name)//undefined
console.log(Phone1.name)//手机
================
//类继承
class Phone2{
constructor(brand,price) {
this.brand = brand
this.price = price
}
call(){
console.log('我可以打电话')
}
}
class SmartPhone2 extends Phone2{
// 构造方法
constructor(brand,price,color,size) {
super(brand,price)
this.color = color
this.size = size
}
photo(){
console.log('拍照')
}
video(){
console.log('视频')
}
}
let xiaolingtong = new SmartPhone2('小灵通',999,'黑色','11inch')
console.log(xiaolingtong)
get和set
// get和set
class phone2{
get price(){
console.log('价格属性被读取了');
return 'hhhh'
}
set price(newVal){
console.log('价格属性被修改了')
}
}
let s = new phone2();
console.log(s.price) //价格属性被读取了
s.price = 'free' //价格属性被修改了
数值扩展
对象方法扩展
1.Object.is判断两个值是否完全相等
console.log(Object.is(120,20)) //false
console.log(Object.is(NaN,NaN)) //true
console.log(NaN===NaN)//false
2.Object.assin对象的合并
const config1 = {
host:'localhost',
port:3306,
name:'root',
pass:'root',
test:'test'
}
const config2 = {
host:'http://atguigu.com',
port:33060,
name:'jumaoleyuan.com',
pass:'hhh',
test2:'test2'
}
console.log(Object.assign(config1,config2))
// host: "http://atguigu.com"
// name: "jumaoleyuan.com"
// pass: "hhh"
// port: 33060
// test: "test"
// test2: "test2"
3.Object.setPrototypeOf设置原型对象 Object.getPrototypeof
const school2 = {
name:'尚硅谷'
}
const cities = {
xiaoqu:['北京','上海','深圳']
}
Object.setPrototypeOf(school2,cities);
console.log(Object.getPrototypeOf(school2));//xiaoqu: (3) ['北京', '上海', '深圳']
//[[Prototype]]: Object
console.log(school2) //{'name':'尚硅谷'}
ES7新特性
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/69df98f70ef42c4207057fa5accb46bb.png)
- async 函数的返回值为 promise 对象,
- promise 对象的结果由 async 函数执行的返回值决定
- await 必须写在 async 函数中
- await 右侧的表达式一般为 promise 对象
- await 返回的是 promise 成功的值
- await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理
// trim用来清除字符串的空白
// trim
let str = ' hhhh '
console.log(str);
console.log(str.trimStart())
console.log(str.trimEnd())
// flat
// 将多维数组转化为低维数组
const arr666 = [1,2,3,[4,5,[5,6]]]
// 参数为深度,是一个数字 默认值是1,将三维转成二维 传2 将三维降低两个维度 成一维
console.log(arr666.flat())
// flatMap
const arr777 = [1,2,3,4]
const result999 = arr777.map(item=>item*10)
console.log(result999)//10,20,30,40
allSettled
// 声明两个promise对象
const p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('商品数据 -1')
},1000)
});
const p2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
// resolve('商品数据 -2')
reject('出错啦')
},1000)
});
// 调用allsettled 方法(始终返回成功)
const result0 = Promise.allSettled([p1,p2]);
console.log(result0)
// const res = Promise.all([p1,p2])==失败返回失败,成功返回成功
// console.log(res)
但是不能使用浮点型转化
console.log(globalThis)
始终指向window 全局对象