JS进阶
一·作用域
局部作用域是在函数作用域内和函数内,局部声明的变量不能在函数外使用。全局作用域在函数外,函数内都能用。
作用域链,优先查找当前作用域,在冒泡一级一级往上查找。
垃圾回收机制:局部变量,未使用就会自动被回收;而全局变量一般不会被回收,关闭页面才会被回收。
标记清除法:从根部扫描对象,能查找到就使用,查找不到就回收。
闭包:内层函数+外层函数的变量
变量提升:var只提升当前作用域的最前面,只提升不赋值;函数也有变量提升,也可以先声明,在写函数。但是函数表达式必须先声明在调用比如说:
fun() //错的
var= function fun() {
console.log(11); 错的
}
var fa //对的
function fa() {
console.log(11);
}
二·函数参数
动态参数,arguments只存在与函数的内部,是一个伪数组传入的参数可以是任意的。
function getsum() {
let sum = 0
for (let i = 0; i < arguments.length; i++) {
sum += arguments[i]
}
console.log(sum);
}
getsum(1, 5, 8)
剩余参数:...other:是一个真数组。...前面是指的是除了a以外的数据元素,这里代码,并不包括1求和,当然这里也可以除多个数据
function getsum(a, ...arr) {
let sum = 0
for (let i = 0; i < arr.length; i++) {
sum += arr[i]
}
console.log(sum);
}
getsum(1, 5, 8)
展开运算符:
const arr = [1, 5, 3]
console.log(Math.max(...arr));
箭头函数
const fun = () => {
console.log(1);
}
fun()
const fa = x => console.log(111);
const f = x => {
console.log(x + x);
console.log(1);
}
const q = uname => ({ uname: uname })
console.log('你好'); //可以返回一个对象,不需要return
箭头函数里面的this指向,只有函数里面才有this,对象里面的this,如果在函数里面,这里的this为window,如果是嵌套函数,this就指的是obj
三·解构赋值
将数组的单元值批量赋值给一系列变量
const arr=[1,2,3]
const[min,midd,max]=arr //min=arr[0] ,midd=arr[1],max=arr[2]
两数交换,记得加分号。[]有这个开头,前面的代码尾部要加分号;
let a = 1
let b = 2;
[b, a] = [a, b]
数组解构:
const [a, b, [c, d]] = [1, 2, [3, 4]]
console.log(a); //1
console.log(b); //2
console.log(c); //3
console.log(d); //4
const [e, f, g] = [1, 2, [3, 4]]
console.log(e); //1
console.log(f); //2
console.log(g); //[3,4]
对象的解构,这里相当于,const uname=user.name
const user={
name:'小明',
age:11
}
const{uname,age}=user
console.log(uname); //小明
console.log(age); //11
对象解构变量改名 旧对象名:新对象名
forEach(ele,index):他不会返回数组,只是遍历,而map会返回数组
filter,筛选数组元素
const arr = [10, 20, 30]
const newarr = arr.filter(item => item >= 20)
console.log(newarr);
四·对象与内置构造函数
利用new Object()构造函数;
自定义构造函数创建对象,快速创建类似对象,函数名首字母大写,并且用new来创建
function Pig(name, age, gender) {
this.name = name
this.age = age
this.gender = gender
}
const p = new Pig('佩奇', 11, '女')
实例对象和方法称为实例成员,实例对象相互独立。而静态成员是写在构造函数身上的,静态成员只能通过构造方法实现
四·内置构造函数
Object静态构造方法:
获得对象属性值,返回的是数组:
const o = { name: 'lii', age: 12 }
console.log(Object.keys(o));
返回{'name','age'}
console.log(Object.values(o)); 返回{'lii',12}
const oo={}
Object.assign(oo, o) 将o拷贝给o
数组reduce累计方法,它可以将数组求和,可以有初始值也可以无初始值
const arr = [1, 2, 4]
const sum = arr.reduce((prev, current) => prev + current) //无初始值 7
const sum = arr.reduce((prev, current) => prev + current,10) 有初始值17
Number的toFixed(n)可以保留几位小数,注意这里是四舍五入的。
五·面向对象
面向对象是把事物分解成一个个对象,然后由对象间份分工与合作。
对象的公共方法可以用prototype,这个是Object的一个属性,不同的对象调用这个创建的方法内存都是公用的。
Star.prototype.sing=function(){
console.log('唱歌');
}
原型函数和构造函数里面的this都是指向实例对象。
再比如说用原型函数自定义函数求和
Array.prototype.sum = function () {
return this.reduce((prev, item) => prev + item, 0)
}
console.log([1, 2, 3].sum());
如果一个对象里有多个构造方法,我们可以给原型对象采取形式赋值的模式,但是这个时候要用constructor重新指回原型的构造函数,如下面这个代码所示
function Star(uname, age) {
this.uname = uname
this.age = age
}
Star.prototype = {
//重新指回创作这个原型的构造函数
constructor: Star,
sing: function () {
console.log('唱歌');
},
dance: function () {
console.log('跳舞');
}
}
原型的继承
继承的时候,原型函数指向父亲构造函数,但是这个时候constructor要指回它本身自己。
function Person() {
this.eays = 2,
this.head = 1
}
function Woman() {
}
Woman.prototype = new Person()
Woman.prototype.constructor = Woman
const pink = new Woman()
console.log(pink.head);
父亲用构造函数,这样子类原型new创建新的父类函数,在给子类创建新的方法,可以与不同子类的构造函数区分开来。
浅拷贝:一般只能拷贝对象里面非函数类的内容,有一下两种方法可以实现浅拷贝
const Obj={
uname:'pink',
age:18,
fiamy:{
ba:'小王'
}
}
const o={}
Object.assign(o,Obj) //方法一
const o={...obj} ///方法二
深度拷贝,一般要用到函数递归的方法,对象里面有数组和对象都需要用到,一般都是先判断是什么,在根据这个给新对象添加一个空数组或者空对象,接下来演示一下
const Obj = {
uname: 'pink',
age: 18,
hobby: ['乒乓球', '足球']
}
const o = {}
function deepCopy(newObj, oldObj) {
for (let k in oldObj) {
if (oldObj[k] instanceof Array) {
newObj[k] = []
deepCopy(newObj[k], oldObj[k])
}
else if (oldObj[k] instanceof Object) {
newObj[k] = {}
deepCopy(newObj[k], oldObj[k])
}
else {
newObj[k] = oldObj[k]
}
}
}
deepCopy(o, Obj)
还有其他方法:lodash拷贝,运用js库可以实现;还可以用JSON的方法实现
const Obj = {
uname: 'pink',
age: 18,
hobby: ['乒乓球', '足球']
}
const o = JSON.parse(JSON.stringify(Obj))
六·异常处理
throw:异常抛出会中断程序
try ...catch,如果try尝试运行代码有错误,catch就会捕获错误信息,err.message可以写出错误信息。finaly,不管程序有没有错误都会执行finaly后面的代码
七·改变this
普通函数谁调用它,this就指向谁
dom.call()可以改变this的指向
const Obj = {
uname: 'pink',
age: 18,
hobby: ['乒乓球', '足球']
}
function fn(x,y){
console.log(this); //原本是指向widow,使用call后指向Obj
console.log(11);
}
fn.call(Obj,1,2)
call()不仅可以改变this 的指向,还能调用函数
apply(返回对象,数组)这个方法与call类似,但是传入的数据是数组,就可以用这个方法求函数最大值或者最小值等等
const arr = [100, 22, 33]
const max = Math.max.apply(Math, arr)
bind(this要指向的对象),返回的是一个函数,dom=dom.bind(),相当于拷贝了一个函数
防抖:单位时间内,频繁触发事件只执行最后一次
节流:单位时间内,频繁触发事件只执行第一次