前端开发必会的JS硬知识

本文简介

  • 前端三座大山是HTML、CSS、JS,而Javascript是前端最核心的部分。
  • 通常来讲,完整的JavaScript=ECMAScript+DOM+BOM
  • 让咱们进入JS的深刻学习旅程吧

js数据类型

数据类型有哪些?有什么特色?

  • 最新的 ECMAScript 标准定义了8种数据类型:
  • 七种基本数据类型 「值类型」:
    1. 布尔值(Boolean),有2个值分别是:true 和 false.
    2. null , 一个代表 null 值的特殊关键字。JavaScript 是大小写敏感的,所以 null 与 Null、NULL或变体彻底不一样。
    3. undefined ,和 null 同样是一个特殊的关键字,undefined 表示变量未赋值时的属性。
    4. 数字(Number),整数或浮点数,例如:42 或者 3.14159。
    5. 任意精度的整数 (BigInt) ,能够安全地存储和操做大整数,甚至能够超过数字的安全整数限制。
    6. 字符串(String),字符串是一串表示文本值的字符序列,例如:"Howdy" 。
    7. 表明(Symbol) ( 在 ECMAScript 6 中新添加的类型)。一种实例是惟一且不可改变的数据类型。 补充:

      typeof Symbol() === 'symbol'; // true Symbol('key') !== Symbol('key'); // true Symbol('key') === Symbol('key'); // false前端

  • 一种引用类型「对象(Object)」 包括:Array Function Date

特色:java

  1. 值类型的赋值,实际就是值的拷贝
  2. 引用类型的赋值,实际就是地址的拷贝

热身训练

请说出如下代码打印的结果es6

if (1 == true) 
    console.log(1)
if (1 === true)
     console.log(2)
if ([]) 
    console.log(3)
if ([] == []) 
    console.log(4)
if ([] === [])
    console.log(5)
if (undefined == null)
    console.log(6)
if ('' == null) 
    console.log(7)
if (NaN == NaN) 
    console.log(8)
复制代码
  • 解析:undefined == null ?二者都是无效值。js规范规定,在比较相等性以前,undefined和null不能转化成其余类型的值,且undefined和null是相等的。
  • 解析:undefined === null ?二者不是同一数据类型。== 比较的是值, === 比较的是值和数据类型

    typeof undefined // undefined typeof null // object数组

  • 解析:'' == null ?
    • null: 该值声明的是一个空对象,没有指向任何的内存空间。
    • '':该字符串声明的是一个对象实例,该实例是一个长度为0的字符串
    • 拓展:str = '' 放在栈内存 str = String('') 指向堆内存
  • 解析:NaN == NaN ?
    • NaN属性(not a number)是表明非数字值的特殊值。
    • 任何值和NaN作比较都是false。
    • 任何数和NaN作运算,结果都为NaN。
    • NaN不和任何值相等,包括它自己

    console.log(isNaN(NaN)) //true console.log(isNaN(10)) //false console.log(isNaN('20')) //false 将'20'转为数字类型20 console.log(isNaN('abc')) //true console.log(isNaN(true)) //false 将true转为1浏览器

浅拷贝与深拷贝

  • 浅拷贝:增长了一个指针指向已存在的内存地址
  • 深拷贝:增长了一个指针而且申请了一个新的内存,使这个增长的指针指向这个新的内存
  • 举个栗子🌰

    const a = [1,2,3]; const b = a; b[0] = 5;
    a = ? // [5, 2, 3]缓存

  1. 这是浅拷贝,由于a和b指向同一块内存地址。当a赋值给b时, 只是将a的数据指针赋值给b,并无开辟属于b的内存空间。
  2. 若是是深拷贝,应该为b开辟独立的内存空间,而且将a的内容拷贝过来。二者互不影响。

深拷贝的实现

let obj = {
    name: 'kk',
    bf: ['a', 1],
    a() {
        console.log('d')
    },
    offer: null
}
function deepClone(origin, target={}) {
    const toStr = Object.prototype.toString,
         arrStr = "[object Array]"
    for(let prop in origin) {
        if(origin.hasOwnProperty(prop)) {
            if(origin[prop] !== null && typeof origin[prop] === 'object') {
                target[prop] = toStr.call(origin[prop]) === arrStr ? [] : {}
                deepClone(origin[prop], target[prop])
            } else {
                target[prop] = origin[prop]
            }
        }
    }
    return target
}

let ans = deepClone(obj)
ans.offer = 'xxx'
console.log(ans, obj)
复制代码

typeof 和 instanceof 的区别

  1. typeof用于判断变量的类型
  • 数值类型 typeof 2 返回 number
  • 字符串类型 typeof 'ac' 返回 string
  • 布尔类型 typeof true 返回 boolean
  • 对象、数组、null, 返回 object
  • 函数 typeof eval 、typeof Date 返回 function
  • 不存在的变量、函数或者undefined, 返回 undefined
  1. instanceof判断某个对象是否被某个函数构造

区别:安全

  • typeof采用引用类型存储值时出现问题,不管引用的是什么类型的对象,都会返回object
  • es引入java的instaceof解决问题
  • instanceof与typeof类似,用于识别正在处理的对象类型。
  • 不一样的是,instaceof要求开发者明确地确认对象为某特定类型

== 和 === 有什么区别?

  • ==只判断值是否相等
  • ===判断值是否相等,类型是否相同

数组、对象那些事

判断数组类型的方法

  1. Array.isArray(arr) => true
  2. Object.prototype.toString.call(arr) => "[object Array]"
  3. arr instanceof Array => true
  4. arr.constructor == Array => true **instanceof和constructor,必须在当前页面声明。若是是父页面引入iframe,也判断不出来**

函数中的 arguments 是数组吗?

  • arguments是类数组,原型(proto)指向的是Object;而真正数组指向Array。
  • document.getElementByTagName 返回的也是类数组,原型指向HTMLCollection.

如何将函数中的arguments转化为真正的数组?

  • Array.from(arguments)
  • [].slice.call(arguments)
  • 扩展运算符(当数组或者对象只有一层的时候,意思是不存在数组嵌套对象,或者嵌套数组这种状况,拷贝是深拷贝。除了第一层是深拷贝,其它层都是浅拷贝) [...arguments]
  • [].concat.apply([],arguments)
  • Array.of(...arguments)
  • Array(...arguments)

Array的forEach等用法

  1. forEach:遍历数组(for)
  2. map: 返回一个数组,不改变原数组的内容
  3. every:每一个元素都符合条件,就返回true

    arr.every((val, index, array)=>val=='a')markdown

  4. some: 只要有一个元素符合条件,就返回true

    arr.some((val, index, array)=>val=='a')闭包

  5. filter: 返回一个数组,里面都是符合条件的元素。

    arr.filter((val, index, array)=>val=='a')app

  6. reduce: 返回一个数 可进行递归、叠加、阶乘,从左到右 (reduceRight 从右到左)

    arr.reduce((prev,cur,index,arr)=>{ // 加法 // return prev+cur // 阶乘 // return Math.pow(prev,cur) return prev**cur })

如何遍历一个对象?

  • for(let prop in obj)
  • object.keys(obj); object.values(obj)
  • object.getOwnPropertyNames(obj)

闭包与做用域

闭包就是可以读取其余函数内部变量的函数

请实现一个“有缓存功能”的加法

let add = (()=>{
    let sum = 0
    return  n=>sum += n
})()
console.log(add(5), add(6), add(1))
复制代码

什么是做用域?细分为哪些做用域?

浏览器给js的生存环境叫做用域。

  • 函数做用域
    • 在函数调用的时候,会建立函数做用域。调用完会摧毁
    • 每一次调用函数都会建立一个函数做用域,而且相互独立
    • 函数做用域能够访问全局做用域的变量,全局做用域不能够访问函数做用域的变量
    • 函数内访问变量,会从自身函数做用域内找,找不到就往上一级做用域找,直到找到全局做用域。若是仍是找不到,就返回ReferenceError
    • 在函数做用域内要访问全局变量,可使用window
  • 全局做用域
  • 块级做用域(下一栏目)

let、const、var的区别?

  1. 何时提出?
  • var是es5提出的,let、const是es6提出的
  1. 变量提高
  • var可以进行变量提高,let、const不能够
  1. 暂时性死区(TDZ)
  • 在块级做用域内,let、const具备暂时死区,一进入做用域内,变量就已经存在,可是在变量声明前不能被访问或者调用,不然会报错 ReferenceError
  1. 重复声明
  • var能够重复声明
  • let、const不能够
  1. 是否存在块级做用域
  • var不存在(一、内部变量可能会覆盖外部变量二、用于计数的循环变量泄露为全局变量)
  • let、const存在
  1. 声明的变量可否被修改
  • var和let能够 const不能够,一旦声明必须当即初始化

更多精彩内容,请关注公众号。

前端交流群(群里大佬如云,会常常分享优秀的文章,前端路上,结伴同行~)

相关文章
相关标签/搜索