js 高级

目录

复习补充:

1.1 变量

2.1 作用域

2.2 作用域链

2.3 闭包

2.4 预解析

2.41 变量 

2.42 函数

2.5 动态参数 arguments

2.6 剩余参数

2.7 箭头函数

2.71 基本形式

2.72 箭头函数的其它形式

2.73 箭头函数的使用

2.8 递归练习

2.81 求6的阶层

2.82 求斐波那契数列:兔子序列

2.9 结构赋值

2.91 数组解构

2.92 对象解构

3.1 面向对象

3.11 字面量创建对象

3.12 构造函数

Array构造函数

3.13 自定义构造函数

3.14 constructor、instanceof

3.15 静态成员、实例成员

3.16 数据传递

3.17 练习题

4.1 字符串

4.11 常用方法

4.12 练习

4.2 公共方法

4.3 原型对象

4.4 继承

5.1 严格模式

5.2 改变函数中的this值

5.3 类

5.31 创建类,实例成员和静态成员

5.32 constructor

5.33 extends

5.34 super

5.35 类的本质

5.4 拷贝

5.41 浅拷贝与深拷贝 


复习补充:

BOM浏览器对象模型(细见主页web api(js进阶)/js基础)

window对象:navigator、location、history、screen(屏幕相关属性)、document

window事件:load、DOMContentLoaded、beforeunload、dragover(拖曳)、drop(鼠标放开时触发)

classList:add、remove、toggle、contains

自定义属性:data-xxx

1.1 变量

var定义的变量相当于给window添加属性,函数相当于给window添加方法

一个变量只定义不赋值 undefined

const声明的变量不准改变,称为常量,定义的常量必须初始化赋值,其它与let无区别

未定义直接赋值的变量为全局变量

2.1 作用域

变量的使用范围

全局作用域:函数外面的作用域,

全局变量:在全局作用域下定义的变量,可以在任意地方使用

局部作用域:函数内部的作用域,

局部变量:在局部作用域下定义的变量,只能在当前函数中使用

块级作用域:ES6中 用{}包裹的代码,类似于局部作用域

尽量少使用全局变量,易报错(即变量污染)

ES6中将parseInt,parseFloat归到Number构造函数中

2.2 作用域链

是否声明变量,若当期那作用域没有这个变量,就会去上级作用域查找

由作用域串联起来的链状结构

let num=1;
function f1(){
    let num=2
    function f2(){
        console.log(num) //打印2
    }
    f2() 
}
f1()  
let num=1
function f1(){
    num=2;
    function f2(){
        num=3;
    }
    f2();
}
f1();
console.log(num)  //打印3
let num=1;
function f1(){
    let num=2;
    function f2(){
        num=3;
    }
    f2();
}
f1();
console.log(num) //打印1

2.3 闭包

一个作用域有权访问另一个作用域的局部变量

作用:延伸变量的使用周期,使用范围

缺点:过多使用易造成内存泄漏

function father(){
    let num=66;
    //闭包
    return function(){
        console.log(num)
    }
}
let o=father();
o();

2.4 预解析

2.41 变量 

会把代码中声明的变量,提前解析到当前(变量的提升)作用域最前面,但是只定义不赋值

let定义的变量不存在变量提升

2.42 函数

会把代码中具有名字的函数提前解析,解析到当前作用域最前面,指定义,不调用

console.log(n);  //打印undefined
fn(); //打印undefined
var n=3;
function fn(){
    console.log(n);
    var n=6;
}
//参数默认值
function fn(uname='阿飞',age=22){
    //形参没有接受实参,那么形参是undefined
    console.log(`我叫${uname}今年${age}岁`);
}
fn('赵云',21);

2.5 动态参数 arguments

arguments用于接受所有实参

function fun(){
    for(let i=0;i<arguments.length;i++){
        console.log(arguments[i]);
    }
}

fun(1,2,3,'a','b','c',4,5,6,7,8,9);

2.6 剩余参数

语法符号:...,置于最末函数形参之前,用于获取多余的实参

function fun(a,b,...c){   //把所有剩余的值给c
    console.log(a,b,c);
}
fun(1,2,3,4,5,6)

2.7 箭头函数

2.71 基本形式

let fn=(a,b)=>{
    return a+b;
}
let re=fn(1,2);
console.log(re);

2.72 箭头函数的其它形式

//若只有一个参数,可以省略小括号
let fn=a=>{
    return a*a;
}
console.log(fn(3));
//若函数体只有一行代码,可以省略大括号
//若大括号省略,会自动返回结果,不需要写return
let fn1=a=>a*a;
console.log(fn1(6));

2.73 箭头函数的使用

window.setInterval(function(){
    console.log('函数体');
},1000);

箭头函数不存在预解析,必须先定义再调用

箭头函数中不存在arguments

箭头函数认为不存在this,箭头中的this指向箭头函数所在作用域的this

事件处理函数中有this不要用箭头函数

<input type="button" value="点击">
<script>
    let btn=document.querySelector('input');
    btn.addEventListener('click',()=>{
        btn.style.background='red'
})
</script>

2.8 递归练习

2.81 求6的阶层

function digui(n){
    if(n==1){
        return 1;
    }
    return n*digui(n-1);
}
console.log(digui(6))

2.82 求斐波那契数列:兔子序列

1、1、2、3、5、8、13、21...其两个数相加等于第三个数

function fb(n){
    if(n==1||n==2){
        return 1;
    }  
    return fb(n-1)+fb(n-2);
}
console.log(fb(6));

2.9 结构赋值

2.91 数组解构

//一一对应 变量的顺序对应数组单元值的位置一次进行赋值操作
let [a,b,c,d,e,f]=['张飞','赵云','关羽','张辽']
console.log(a,b,c,d,e,f);
//变量多值少
let [a,b,c,d,e,f,g,h]=['张飞','赵云','关羽','张辽']
console.log(a,b,c,d,e,f,g,h)   //剩余的变量e,f,g,h值为undefined
//变量少值多
let [a,b,c]=['张飞','赵云','关羽','张辽']
console.log(a,b,c);  //多的值张辽不取
//按需取值
let [,a,b,c]=['张飞','关羽','赵云','张辽']
console.log(a,b,c)  //a:关羽,b:赵云,c:张辽
//剩余值
let [,a,b,...c]=['张飞','赵云','关羽','张辽','许褚']
console.log(a,b,c); //a:赵云 b:关羽 c:[张辽,许褚]
//复杂情况
let [,,a,b,[,c,d]]=['张飞','赵云','关羽','张辽',['林冲','鲁智深','武松','宋老板']]
console.log(a,b,c,d); //a:关羽 b:张辽 c:鲁智深 d:武松

2.92 对象解构

//取谁拿谁
let {uname,sex}={
    uname:'张三丰',
    age:22,
    sex:'男',
    score:99,
    index:6,
}

console.log(uname,sex);  //张三丰  男

let不能重复定义同一个变量,若遇到已经定义可用:改值

let uname='阿飞'
//用冒号改值
let {uname:userName,sex}={
    uname:'张三丰',
    age:22,
    sex:'男',
    score:99,
    index:6,
}
console.log(userName,sex);   //张三丰 男

对象里面套对象

let {dog:{uname}}={
    uname:'张三丰',
    dog:{
        uname:'小狗子',
        age:1,
    },
    cat:{
        uname:'小猫咪'
    },
    age:22,
    sex:'男',
    score:99,
    index:6,
}
console.log(uname) //张三丰
function person({uname,age,sex}){
    console.log(`我叫${uname}今年${age}岁是${sex}性`)
}
person({uname:'阿飞',age:22,sex:'男'})

3.1 面向对象

面向过程:步骤过程为准,强调事件的流程顺序

面相对象:以对象为核心,强调事件的角色、主体

3.11 字面量创建对象

let obj={
    //属性名:属性值
    //键值对
    //成员
    uname:'张三丰',
    age:22,
    sex:'男',
    taiji:function(){
        console.log('打太极');
    }
}
    console.log(obj.uname);
    console.log(obj['age'])
    obj.taiji();

    for(let key in obj){
        console.log(obj[key]);  //uname age sex taiji函数
    }

3.12 构造函数

构造函数一般用于和new搭配使用,创建对象

内置构造函数:Object,创建对象,

let obj=new Object();
//添加东西
obj.uname='阿飞';
obj.age=22;
obj.xiao=function(){
    console.log('方法');
};
console.log(obj);
Object.keys(obj);  //获取对象的所有键
Object.values(obj);  //获取对象的所有值

如果构造函数不需要参数,那么可以省略小括号

let obj=new Object;
obj.uname='张飞';
console.log(obj);  //{uname:张飞}

正则构造函数:let reg=new RegExp(/abc/);

Array构造函数

let ary=new Array(1,2,3);

console.log(ary);

任何一个属性都是Array构造函数的实例化对象

常用方法:

concat():用于拼接为新数组

let arr=[1,2,3];
let arr1=['a','b','c'];
let reArr=arr.concat(arr1);
console.log(reArr);

join():用于连接数组的每个元素成为字符串

let arr=['a','b','c'];
let str=arr.join('');
console.log(str); //abc

reverse():翻转数组顺序

indexOf():查找某个元素在数组中首次出现的索引位置,找不到就是返回-1

lastIndexOf():查找某个元素在数组中尾次出现的索引位置,找不到就返回-1

Array.from(伪数组):把伪数组转换为真数组必须有length属性

find():用于查找首次出现满足条件的值,并返回

findIndex():用于查找首次出现的满足条件的值,并返回所在索引值

some():有一个满足返回true

every():全部满足返回true

filter():满足条件的元素放到新数组返回

map():把回调函数结果放到新数组里面

forEach():用于遍历数组

let arr=['a','b','c','d','e'];
arr.forEach(function(item,index,o){
    //第一个参数:代表数组的每一项(每个元素)
    //第二个参数:代表数组的每一项的索引值
    //第三个参数:代表当前数组本身
    console.log(item,index,o);
})
arr.forEach(item=>{
    console.log(`姓名:${item.uname},年龄${item.age},性别${item.sex}`);
});

sort():排序  isArray():判断一个值是否是数组

//sort:排序
let arr=[3,16,22,66,123,99];
//正序排列:
let re=arr.sort(function(a,b){return a-b;});
//倒序排列
let re1=arr.sort(function(a,b){return b-a;});
console.log(re); //3 16 22 66 99 123
console.log(re1);//123 99 66 22 16 3

3.13 自定义构造函数

function Person(uname,age,sex){
    //设置属性
    this.uname=uname;
    this.age=age;
    this.sex=sex;
    this.eat=function(){
        console.log('吃饭');
    }
}
//实例化对象
let o=new Person('张三丰',22,'男');
console.log(o);

3.14 constructor、instanceof

function A(){}
function B(){}
let obj=new B();
//instanceof:用于判断一个对象是否是另一个构造函数的实例对象
//对象 instanseof 构造函数 
console.log(obj instanceof B); //true
//constructor:指回构造函数本身
console.log(obj.constructor);   //函数B

3.15 静态成员、实例成员

在构造函数身上直接添加的成员,称为静态成员(静态属性静态方法)

静态成员只能由构造函数访问

构造函数内部为实例对象准备的成员,称为实例成员

实例成员只能由实例对象访问

3.16 数据传递

变量传递给另一个变量

值传递:会把数据复制一份传递(简单类型)

引用类型:把数据地址复制一份(引用类型)

3.17 练习题

let n=10;
let m=11;
function fn(a,b){
    a=100;
    b=200;
}
fn(n,m);
console.log(n,m);  //10 11

let o={uname:'张三丰',age:22,sex:'男'};
function fun(obj){
    obj.uname='李寻欢';
}
fun(o);
console.log(o); //{uname:'李寻欢',age:22,'男'}
let arr=['a','b','c','d','a']
let newArr=[];
//遍历arr的每一个元素,在newArr中查找,若找不到就把这个值添加进去
for(let i=0;i<arr.length;i++){
    if(newArr.indexOf(arr[i])==-1) newArr.push(arr[i]);
}
console.log(newArr);

4.1 字符串

4.11 常用方法

trim:用于去除字符串两端空白 str.trim()

split:分割字符串

toLowerCase:把字母转成小写

toUpperCase:把字母转成大写

indexOf:首次出现的索引值

lastIndexOf:尾次出现的索引值

slice(start,end):从索引值为start的位置截取字符串到end索引位置

如果只有一个参数,会从该参数索引值截取到最后

substring(start,end):从索引值为start的位置截取字符串到end索引位置

4.12 练习

let str='猫猫很可爱,超级喜欢,要有一只属于自己的';
let startIndex=str.indexOf('喜');
let endIndex=str.indexOf('属');
let re=str.substring(startIndex,endIndex+1);
console.log(re);

4.2 公共方法

toString() undefined和null不可使用

let num=123;

console.log(num.toString()); //将123转换为字符串

valueOf:获取原始值

let num=new Number(666);

console.log(num.valueOf());

4.3 原型对象

构造函数的一个属性 :构造函数.prototype

作用:共享方法:节省内存,当实例对象找不到成员的时候会找原型对象上的成员

构造函数.prototype.constructor:用于指回构造函数本身

每一个对象都有一个属性:__proto__

作用:用于指向原型对象

function Person(){}

let obj=new Person()

obj.__proto__=Person.prototype

原型链:由原型构成的链状

4.4 继承

//构造函数
function Person(){
    this.head=1;
    this.eyes=2;
    this.legs=2;
    this.say=function(){console.log('say');}
    this.eat=function(){console.log('eat');}
}
function Chinese(){
    this.language='汉语';
    this.skin='yellow';
}
//继承:
//把对象赋值给原型对象
Chinese.prototype=new Person();
//指回构造函数本身
Chinese.prototype.constructor=Chinese;
//实例对象
let c1=new Chinese();
console.log(c1);

5.1 严格模式

js开启严格模式 "use strict"
放在全局开头,全局开启严格模式
放在函数开头,代表这个函数内部严格
1、变量必须先定义再使用
2、普通函数中的this指向undefined
3、函数的形参不准重名

5.2 改变函数中的this值

函数.call(this指向的参数,剩下的参数给函数参数准备)

function fun(a,b){
    console.log(this,a,b)//{uname:'张三丰',age:22} 1 2
}
let obj={uname:'张三丰',age:22};
fun.call(obj,1,2)

函数.apply(this指向的参数,[剩下的参数])

function fn(a,b){
    console.log(this,a,b); //{uname:'阿飞'} 111 222
}
let obj={uname:'阿飞'};
fn.apply(obj,[111,222]);
let arr=[23,66,33,19,4,7];
let re=Math.max(...arr);
console.log(re);//66

函数.band()只会改变函数指向不会让函数立即执行

let btn=document.querySelector('input');
btn.addEventListener('click',function(){
    //禁用按钮
    this.disabled=true;
    //开启定时器
    window.setTimeout(function(){
        this.disabled=false;
    }.bind(this),5000);
})

5.3 类

5.31 创建类,实例成员和静态成员

class Person{
    //实例成员
    uname='张三丰';
    age=23;
    sex='男';
    say(){
        console.log('方法');
    }
    hi(){
        console.log('hi');
    }
}
//实例化
let obj=new Person();
console.log(obj.uname);//张三丰
obj.say();//方法

静态成员添加static

class Person{
    //静态成员
    static language='汉语';
    static skin='yellow';
    static eat(){
        console.log('吃')
    }
}
let obj=new Person();
console.log(obj)

5.32 constructor

类中固定的方法名

方法在实例化时立即执行

接收实例化时传入参数

并非是类中必须要存在的方法

class Person{
    constructor(uname,age){
        this.uname=uname;
        this.age=age;
    }
    say(){
        console.log('说话');
    }
}
let obj=new Person('张三丰',22);
console.log(obj); //Person{uname:"张三丰" age:22 __proto__}

5.33 extends

用于类的继承

class Father{
    constructor(uname,age){
        this.uname=uname;
        this.age=age;
    }
    happy(){
        console.log('心情要美');
    }
}
//继承
class Son extends Father{}
let obj=new Son('人',2);
console.log(obj); //Son{uname:"人" age:2}

5.34 super

如果子类有自己的constructor,必须通过super才可以调用父类的方法

class Father{
    constructor(uname,age){
        this.uname=uname;
        this.age=age;
    }
    happy(){
        console.log('心情要美');
    }
}
//继承
class Son extends Father{
    constructor(uname,age,score){
        //先调用super,再设定自己的成员
        super(uname,age)
        this.score=score;
    }
    happy(){
        //就近原则 如果要调用父类里面的方法,用super
        super.happy();
        console.log('嘻');
    }
}
let obj=new Son('人',2,9);
console.log(obj);
//就近原则
obj.happy();

5.35 类的本质

函数

//es6之前
function Person(){}
let obj=new Person();
//es6
class Person{}
let obj=new Person();

5.4 拷贝

5.41 浅拷贝与深拷贝 

只拷贝对象外面一层的简单数据,复杂类型无法拷贝

let obj={
    uname:'张三丰',
    age:22,
    sex:'男',
    color:['red','blue','yellow'],
    message:{
        score:99,
        index:6,
    }
}
let newObj={}
//浅拷贝
//方法一:
Object.assign(newObj,obj);
//遍历
//方法二:
for(let key in obj){
    newObj[key]=obj[key]
}
obj.message.index=666;
console.log(obj,newObj);

//深拷贝
function kaobei(newObj,obj){
    for(let key in obj){
        if(obj[key] instanceof Array){
            newObj[key]=[];
            kaobei(newObj[key],obj[key]);
        }else if(obj[key] instanceof Object){
                newObj[key]={};
                kaobei(newObj[key],obj[key])
            }else{
              newObj[key]=obj[key];  
           }
    }
}

kaobei(newObj,obj);
console.log(obj,newObj);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值