Day02/Js基础复习-01

目录

定义变量关键词

基本数据类型 

引用类型 

字符串常用方法 

基本数据类型和引用数据类型区别

数据类型的判断

浅拷贝和深度拷贝

函数知识点 

函数闭包 

作用域 

原型和原型链

继承方式


定义变量关键词

var:

  • 可以被重复声明
  • 有函数作用域和全局作用域
  • 会提前声明,值为undefind
  • 可以挂载在window上

let

  • 不可以重复声明
  • 不可以预解析,必须定义后才能赋值
  • 有函数作用域,块作用域和全局作用域
  • 实现方式:通过立即执行函数,模拟块作用域
    (function(){
      var c =3
      console.log(c) 
    })()
    console.log(c) //全局拿不到c的值

const

  • 不能重新复值
  • 定义时就必须赋值,对于基本数据类型的值,修改值时会报错。但是如果修改引用类型数据时,只会检查数据存放的指针,不会具体检查它的属性。
  • 实现方式:
    // 实现const
    function __const( key,value){
        // 判断window对象身上是否有当前属性
        if(window.hasOwnProperty(key)){
            throw new Error("不能重复声明")
        }
        if(!value){
            throw new Error("声明时请赋值")
        }
        window[key]=value
        // 通过Object.defineProperty监听数据变化
        Object.defineProperty(window,key,{ 
            get(){
                return value
            },
            set(newvalue){
                // 修改时不让修改
               if(newvalue!=value)
                 throw new Error("不能重新赋值")
            }
        })
    
    }
    
    __const("text",1)
    console.log(text)
    

基本数据类型 

number

  • 十进制数字
  • 浮点数
  • 其他进制数字 
  • 科学计数 2e^-1
  • NaN  非数字  记住NaN!=NaN,如果需要判断使用Number.isNaN() / isNaN()来判断。两者区别在于,Number.isNaN(data)要同时满足data类型为number,并且值为NaN。而isNaN会将类型转成number,然后在判断是否为NaN

string: 字符串

boolean: 布尔类型,值为true和false

undefined: 已定义但未赋值。

null:对象类型初始时手动赋值为null

symbol: 独一无二的值,不会重复。

bigint:超大整数最大值为2的53次方-1

null 与 undefined 区别: 作者在设计时参考Java设计了null,但是null为对象并且会自动隐式转成0,于是设计了undefined。

面试题:

精度丢失:0.1+0.2=0.300004

原因:因为在计算机最底层,数值的运算和操作都是采用二进制实现的,所以计算机没有办法精确表示浮点数,而只能用二进制近似相等的去表示浮点数的小数部分。

解决方案:先化整计算,在相除(1+2)/10

引用类型 

object:对象常用方法

  • Object.keys(),可以用来判断是否是空对象
  • Object.values()
  • Object.entries()
  • Object.assign() // 可以实现浅拷贝
  • Object,prototype.toString().call()
  • 解构赋值,拓展运算符
  • 注意对象的key只能是string类型,如果你设置成key为对象的话会隐式转为字符串 例如:{a:1} => '[object Object]' ,这个与Map类型不同。

function:常用方法改变this的指向

  • call(this的指向,c1,c2)
  • appy(this的指向,[参数])
  • bind(this的指向,c1,c2)不同于上两个,call和apply方法都是在调用之后立即执行的。而bind调用之后是返回原函数,需要再调用一次才行。

arry:常用方法

  • push:向尾部添加一个或多个数据
  • pop:删除最后一个数据
  • unshift:向头部一个或多个数据
  • shift:删除头部第一个数据
  • splice:三个参数 ,开始索引,删除的数目,插入的新数据(从开始索引的位置)
  • join:数组转字符串
  • sort:数组正序排序   // 之前原理是通过快排和插入排序,现在是冒泡
let arr=[1,3,0,3,6,8,3,7]
let res=arr.sort((a,b)=>{
    console.log("a="+a,"b="+b)
    return a-b//正序
    //return b-a //逆序

})
console.log(res,"res")
//类似数据结构的插入排序法

  • reverse:反向排序
  • includes:判断是否存在某个字符
  • indexOf:同上,但是返回值不同
  • 解构赋值,拓展运算符

     一些常用遍历方法

  • filter:过滤符合条件的数据
  • map:更改每项数据结构
  • reduce:一般用于计数,计算总价,数量等
  • some:遍历多次有一次满足返回值条件,整体返回值为true
  • every:  整体满足条件返回true
  • find:找到数组中第一个满足返回值条件的数据
    // 实现map
    Array.prototype.Map = function(callback){
        // this为数组实例
        const len = this.length;
        let arr = []
        for(let i= 0 ; i< len; i++){
            arr[i] = callback(this[i] , i , this)
        }
        return arr;
    }

字符串常用方法 

  • splite:将字符串转成数组,处理数据常用
  • indexOf:查看是否含有指定内容
  • replace:替换字符,一般结合正则表达式
  • trim:去除两端空格
  • slice:截取指定内容,不会影响原字符串

基本数据类型和引用数据类型区别

两者作为函数的参数进行传递时:

  • 基本数据类型传入的是数据的副本,原数据的更改不会影响传入后的数据。
  • 引用数据类型传入的是数据的引用地址,原数据的更改会影响传入后的数据。
两者在内存中的存储位置:
  • 基本数据类型存储在栈中。
  • 引用数据类型在栈中存储了指针,该指针指向的数据实体存储在堆中。

数据类型的判断

  • 基础类型使用typeof
  • 判断引用类型Object.prototype.toString.call()
  • 通过构造器  constructor.name 拿到构造器名称
  • instance of  :A instanceof B 可以用来判断 A 是否为 B 的实例,但它不能检测 null undefined

浅拷贝和深度拷贝

浅拷贝只复制指向某个对象的指针,而不复制对象本身。浅拷贝的实现方式有:
  • Object.assign():需注意的是目标对象只有一层的时候,是深拷贝;
  • 扩展运算符;
深拷贝就是在拷贝数据的时候,将数据的所有引用结构都拷贝一份。深拷贝的实现方式有:
  • 手写遍历递归赋值;
  • 结合使用JSON.parse()JSON.stringify()方法。 // 但是这个要注意JSON 不支持  undefined ,函数等类型。
  • 使用lodash中_.cloneDeep()方法

函数知识点 

普通函数:       

  •  this的指向:全局作用域中的函数:其内部this指向window;对象内部的函数:其内部this指向对象本身; 构造函数:其内部this指向生成的实例;applycallbind改造的函数:其this指向第一个参数;

箭头函数

  • 箭头函数this指向:箭头函数没有自己的 this ,看其外层的是否有函数,如果有,外层函数的 this 就是内部 箭头函数的this ,如果没有,则 this window
  • 箭头函数不能做构造函数,生成实例。

立即执行函数

  • 一般用于解决闭包问题
  • (fuction(){//执行语句})()

函数闭包 

  • 闭包:定义在一个函数内部的函数。其中一个内部函数 在包含它们的外部函数之外被调用时,就会形成闭包。
  • 闭包用途:
    1 、读取函数内部的变量
    2 、让这些变量的值始终保持在内存中。不会再 f1 调用后被自动清除。
    3 、方便调用上下文的局部变量。利于代码封装。
    原因: f1 f2 的父函数, f2 被赋给了一个全局变量, f2 始终存在内存中, f2 的存在依赖 f1 ,因此 f1 也始终存在内存中,不会在调用结束后,被垃圾回收机制回收。
  • 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网 页的性能问题,在IE 中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除,或者通过立即执行函数。

作用域 

全局作用域:

     预编译

  1. (针对于var)先生成Go对象
  2. 查找var声明的变量,赋值为undefind
  3. 查找函数声明,进行赋值
  4. 按照代码执行的顺序,再次赋值

函数作用域:

     预编译:

  1. (也针对于var)创建Ao对象
  2. 查找形参和变量声明,赋值为undefind
  3. 将实参和形参统一,进行赋值
  4. 在函数中找函数声明,重新赋值
  5. 函数执行,对未执行代码进行重新赋值

块作用域:let,const声明的变量独有,能够在{}块中保留变量当前的值。

  • 每个函数执行都会产生一个作用域链,当函数需要查找某个变量时,会在自身的ao对象中查找,如果找不到在上一个函数的ao继续找,直到找到全局go对象上,如果还没有就undefined.
  • 当一个函数中声明了其他函数,在其他函数产生的AO和外部函数的AO指向同一个地址,如果在其他函数内部修改了外部的某个值,外部函数的Ao值同样会发生变化。

 原型和原型链

  • 原型的概念 JavaScript的象中都包含了一个 [proto] 内部属性,这个属性所对应的就是自身的原型
  • 原型链的概念 当一个对象调用自身不存在的属性/方法时,就会去自己 [proto] 关联的前辈 prototype 对象上去找,如 果没找到,就会去该 prototype 原型 [proto] 关联的前辈 prototype 去找。依次类推,直到找到属性/方法或 undefined 为止。从而形成了所谓的原型链

继承方式

  • class+extends
//类模板 
class Animal { 
    constructor(name){ this.name = name } 
}
//继承类
 class Cat extends Animal{
//重点 extends方法,内部用constructor+super 
    constructor(name) {
        super(name); //super作为函数调用时,代表父类的构造函数 
    }
    //constructor可省略 
    eat(){ 
        console.log("eating")
     } 
}
  • .原型继承
//类模板 
function Animal(name) { 
    this.name = name; 
}

//添加原型方法 
Animal.prototype.eat = function(){ 
    console.log("eating") 
}

function Cat(furColor){ 
    this.color = color ; 
};

//继承类 
Cat.prototype = new Animal()

//重点:子实例的原型等于父类的实例
  • 通过构造函数
function Animal(name){ 
    this.name = name 
}

function Cat(){ 
    Animal.call(this,"CatName")
    //重点,调用父类的call方法
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值