看了一些资料,结合ES6、高程和MDN,对JS核心知识点进行了梳理。由于篇幅有限,这里只对我认为重要的知识做了介绍。一些常识性的东西可以参考高程,另外一些核心知识点的扩展可以参考我其他的文章。
数据类型(7种)
基础类型
- null:空指针,所以typeof null ==>Object(底层二进制码全部为0,而js固定如果前三个为0就是object)
- undefined:定义了未赋值
- Number:数字
- String:字符串
- Symbol:一种实例是唯一且不可改变的数据类型。
- Boolean:布尔值
引用类型
- Object:具体可以是Array,Function,RegExp,Date
栈内存和堆内存
为了更好的理解栈内存和堆内存,给一张图
栈内存就是线性表,因为基础类型简单,内存固定,所以给个线性表就能存
堆内存是啥,这个堆和树结构堆没啥关系,你可以把它理解成
一大堆(坨?) 里面的东西内存大小并不固定
声明变量
var
特点
:变量提升,没有块级作用域
说到var肯定要提变量提升:当前作用域,js(函数)执行前,浏览器会把带var或者function进行提前声明和定义
- 变量只声明,函数是声明+赋值,自执行函数定义和执行一起完成了
- 不受逻辑判断条件影响
- return 下面的也提升,但是return 里面的不提升
- 重复的声明可以,重新赋值即可,但是变量和方法名字不能冲突
const
特点
:常量,地址不变,但是属性可以变
当我们定义一个const对象的时候,我们说的常量其实是指针,就是const对象对应的堆内存指向是不变的,但是堆内存中的数据本身的大小或者属性是可变的。而对于const定义的基础变量而言,这个值就相当于const对象的指针,是不可变。
既然知道了const在内存中的存储,那么const、let定义的变量不能二次定义的流程也就比较容易猜出来了,每次使用const或者let去初始化一个变量的时候,会首先遍历当前的内存栈,看看有没有重名变量,有的话就返回错误。
let:
特点
:块作用域,暂时性死区(TDZ),不进行变量提升,不允许重复声明
//只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。所以下面代码不报错,外层作用域和里层作用域都有一个tmp
let tmp = 123;
if (true) {
let tmp =123;
}
//ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
let tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
import:es6模块化解决方案
class:es6继承解决方案
判断数据类型
typeof
typeof '' // ==> string
typeof 1 //==> number
typeof true //==>boolean
typeof undefined //==>undefined
let b = Symbol() ; typeof b //==>symbol
-----------------下面的判断不了实际类型了-----------------------
typeof function fn(){} //==>function
typeof null //==>object
typeof [1,2,3] //==>object
typeof {} //==>object
instanceof
//缺点2的一个演示
let arr = [1,2,3]
arr instanceof Array //==>true
arr instanceof Object //==>true
----------------------------
//缺点1的一个演示
//强行改变原型影响instanceof的判断
var a = {}
a instanceof Function
false
a.__proto__ = Function
ƒ Function() { [native code] }
a instanceof Function
true
constructor
[].constructor === Array //true
[].constructor.constructor === Function // true
[].constructor === Object //false
isNaN:
console.log(isNaN("1px")); //true
//先调用Number('1px'),返回NaN,
//然后再调用isNaN(NaN)返回true
//燃鹅 '1px'客观并不是NaN
Object.prototype.toString.call()
Object.prototype.toString.call(null) // ==> [object Null]
Object.prototype.toString.call([]) // ==> [object Array]
isArray
Array.isArray([]) //==>true
Object.is
let a = null
Object.is(a , null) //==>true
Object.is(NaN , NaN) //==>true
类型转化
这一块内容太多,太杂了,其实我不怎么想写,因为很少有人会这么写代码。但是这块太重要了,面试必考。建议大家掌握这块的核心内容以及原则,不要关注奇淫巧技。
自动装包
三种包装类型:Number,Boolean,String
let s1 = '123'
let s2 = s1.slice(2) // a是基本类型,它是没有slice方法的这里实际上后台完成了一个自动装包
---下面是实际发生的事---------
let s1 = new string('123')
let s2 = s1.slice(2)
s1 = null //注意这里用完就销毁了
//所以如果添加某个属性后面是调用不出来的
let s1 = '123'
s1.color = 'red'
console.log(s1.color) // ==> undefind
//这里特别说一下 为什么123.toString会报错 //Uncaught SyntaxError: Invalid or unexpected token
//这个是语法错误,因为编译的时候没有办法判断是小数点还是调用方法
要么用括号包起来 要么用..
这些类型(构造函数)基本都重写了它们的tostring方法
Number
Number :将其他数据类型的值强制转换成number类型;
Number(true) // 1
Number(false) // 0
Number({}) //NaN
Number(undefined) // NaN
Number(null) // 0
Number([]); // 0
Number([1]); // 1
Number([1,2]); // NaN
Number(['1px']); // NaN
Number("") // 0
Number("1") // 1
Number("1px") // NaN
???这么复杂 ???
没办法,背也得背下来 。因为很多操作符、方法会自动装包,自动调用Number,所以不掌握这块很容易出bug
和number相关的方法及运算符
1.parseInt
全局方法,经常用于字符串提取数字的方法; 把字符串中从左到右依次识别,直到遇到一个非有效数字,停止,把找到的数字返回;
parseInt("12px12") // 12
parseInt("12.666.777px12") // 12
parseInt("px12.666px12") // NaN
parseInt("") // NaN
parseInt(true) // NaN
parseInt({}) // NaN
parseInt([]) // NaN
parseInt(null) // NaN
parseInt(undefined) // NaN
2.toFixed
保留小数点位数的方法,返回值是一个字符串
;
3.位运算
// 转整数
~~1.2 //1
~~'1.2' //1
~~'1.2px' //0 先调用Number()转换成数字,再调用~~转换成整数 ~~NaN 0
4.-转化
会先把字符串转换成数字(Number
),然后再进行计算,注意NaN,undifined参与的任何计算都是NaN
console.log("6" - 2);//==> 4
console.log("5px"-"4")//==> NaN (NaN-4还是NaN)
// * 号类似
1*‘1.1’ //1.1
1*'1.1px' //NaN
5.+转化
具体调用string还是number请看下表 遇到string或者obj转成string就行了
|| undefined | null | boolean | number | string | object |
=========================================================================
undefined || number | number | number | number | string | string |
null || number | number | number | number | string | string |
boolean || number | number | number | number | string | string |
number || number | number | number | number | string | string |
string || string | string | string | string | string | string |
object || string | string | string | string | string | string |
//字符串、和任何类型相加都是调用String
var a = typeof 10 + true + [] + null + undefined+{};
console.log(a); //==>numbertruenullundefined[object Object],{}
console.log("6px"+undefined); ==> 6pxundefined
console.log(NaN+"undefined");==> NaNundefined
//经典面试题
[1,2]+[2,1] //==>都调用toString '1,2'+'2,1'===>'1,22,1'
console.log({name:'fyy'}+'11')
[object Object]11
/*腾讯面试题*/
let result = 1+null+true+undefined+'Tencent'+false+[]+undefined+null;
console.log(result); //NaNTencentfalseundefinednull
6.布尔值Boolean
其他数据类型转布尔类型是false有且只有五个值: 0 "" NaN null undefined
所以boolean({}) 或者boolean([]) 都是真
==和===
===是全等,==是类型转化后再判断,规则比较复杂。这里我认为除了准备面试需要看看,平时基本不会用,所以这个知识性价比非常低,学了用不到也会忘,大家自己把握,详细规则可以搜我其他文章
平时除了判断a是否是undefined或者是null(jq源码里面都用法
)都时候其他情况下都用===
console.log(null==undefined) // true
console.log(undefined==undefined) // true
这里再补充一个,判断数字和字符串相等的以后用==也非常好用。比如后台返回的数据一会是1一会儿是‘1’你需要封装一个通用方法的时候,可以使用==来进行判断
还是说一下吧 对象==对象 比较地址 对象==字符串 对象变字符串再比较 NaN==NaN false null==undefined true 其他情况 只要两边不同 全部转换为数字
console.log([]==false); 对象==布尔 全部转化为数字 0==0 true
console.log(![]==false); ![]先运算 false==false 全部转化为数字 true
总结
本期文章估计大家看的很烦,无奈,我写起来也非常枯燥。因为不仅得讲规则,还得写用例。还是那句话,建议大家掌握核心知识点,细枝末节的东西就随意啦。这一期文章还有许多东西可以展开来讲,篇幅有限,我将会在后面的文章中一一涉及。感谢大家的阅读,本人水平有限,如果有不对的地方请在评论区指出。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!