javascript的发展史
关于前端的发展史,推荐看阮一峰老师的这个解说,介绍了关于javascript
语言的诞生、javascript
与ECMAScript
的关系、javascript
与Java
的关系(这就跟苹果与苹果手机的问题类似吧,哈哈)、javascript
的版本以及它发展的过程等等;链接地址https://javascript.ruanyifeng.com/introduction/history.html
浏览器
客户端通过网址去访问服务器,服务器返回的是前端代码,浏览器把返回的代码进行解析渲染,最后渲染成为用户可看见的页面
=>这就是浏览器的内核或者引擎做的事情,不同的浏览器渲染机制不一样,因为它们采用不同的内核来进行处理
按照不同的内核浏览器的分类
以谷歌浏览器webkit
内核为主 (V8
引擎)
- 谷歌浏览器
Chrome
- 苹果浏览器
Safari
- 国产浏览器
- 360普通浏览器
- 360极速浏览器
- 猎豹浏览器
- 搜狗浏览器
- QQ浏览器
- UC浏览器
- …
- 欧朋浏览器
Opera
(v14版本的时候)
gecko内核
- 火狐浏览器
Firefox
Trident内核
- IE浏览器
Presto内核
- 欧朋
控制台的使用
打开开发者工具:F12/FN + F12 (再或者浏览器页面: 右击–>检查)
Elements
包含了当前页面中所有的结构和样式,基于它可以快速查看和调整页面的样式和结构等Console
控制台 ,在JS中,我们可以向控制台输出一些内容,来进行项目的调试;如果项目程序出现问题,也可以在控制台查看报错信息,也可以在控制台编写代码,做一些测试…Network
包含了当前页面所有向服务器发送的HTTP
请求信息,一般用于前后端数据交互中的BUG
调试以及页面中的性能优化Sources
包含了当前项目的源代码Application
可以看到本地存储的信息(Cookie/LocalStorage/SessionStorage...
)以及当前网站中所有加载的图片等信息(抓取一些图片下来)- …
- 开启手机模拟器
Toggle Device Toolbar
职业习惯:打开浏览器,第一步就是F12打开控制台
JavaScript中的输出方式
1.console 控制在浏览器控制台输出的
-
console.log()
控制台输出日志(特点:输出任意数据类型的数据,控制台展示的也是对应的数据类型,可以一次性输出多个值) -
console.dir()
控制台详细输出(特点:输出一个对象或者一个值的详细信息,但是dir不可以输出多个值) -
console.table()
把数据以表格的形式输出在控制台(特点:把多维的JSON数据以表格的形式输出) -
console.time() console.timeEnd()
计算出time/timeEnd
中间所有程序执行所消耗的时间。预估时间:受到当前电脑性能的影响 -
console.warn()
以警告的方式输出
console.time('AA');
for (let i = 0; i < 99999999; i++) {}
console.timeEnd('AA'); //=>AA: 218.3701171875ms
2.window提示框
alert()
弹框输出- 是在浏览器窗口中弹出一个提示框,提示框中输出指定的信息
- 需要等到
alert
弹出框,点击确定关闭后,后面的代码才会继续执行(alert
会阻碍主线程的渲染) alert
弹出的内容都会默认转化为字符串
confirm()
弹框输出- 相对于alert来说,给用户提供了 ‘确定’ 和 ‘取消’ 两种选择
- 创建一个变量,用来接收用户选择的结果,
true
点击的是确定false
点击的是取消
prompt()
弹框输出- 在
confirm
的基础上给用户提供书写操作的原因等信息 - 点击的是取消,返回结果是
null
,点击的是确定,会把用户输入的原因信息返回
- 在
let flag = confirm('今天大家都好好学了吗?');
console.log(flag);
let reason = prompt('确定要删除此信息吗?');
console.log(reason);
3.向页面指定的容器中插入内容
document.write()
- 和
alert
一样,写入的内容最后都会转换为字符串,然后再写入
- 和
innerHTML/innerText
- 向指定容器中插入内容(插入的信息也会变成字符串再插入)
innerHTML
能够识别标签,而innerText
会把所有内容当做普通的文本- 添加的内容会覆盖原来的内容,想要不覆盖使用
+=
value
向页面表单元素中输入内容
document.write('AA');
document.write(10);
//结构
<div id="box">
<h1>哈哈</h1>
</div>
///*JS操作*//
let box = document.getElementById('box');
box.innerHTML = "内容1"; //=>覆盖原始的所有内容
box.innerText = "内容2";
box.innerHTML += "内容1"; //=>在原始内容上继续增加
box.innerText += "内容2";
box.innerHTML = "<strong>我是重点内容</strong>";
box.innerText = "<strong>我是重点内容</strong>";
//结构
<input type="text" id="userName">
//JS操作
let userName = document.getElementById('userName');
userName.value = "我是在JS中插入的内容";
JS组成的三部分
ECMAScript(ES3/ES6~9)
定义了JS的语法规范:定义了语言本身的变量、数据值、操作语句、内存管理、逻辑处理…等内容DOM (document object model)
文档对象模型,提供对应的属性和方法,可以让JS操作页面中的DOM元素BOM (browser object model)
浏览器对象模型,提供操作浏览器的属性和方法
注意:现在项目开发,一般都是基于Vue/React
完成的,基于这两个框架,我们已经不去操作DOM
了,我们操作数据,由框架本身帮助我们完成DOM
的操作
JS的变量 variable
变量:就是起了一个名字,用来存储(指向)或者代表某个值的(它是一个虚的东西,值才是实在的东西)
JS中创建变量的几种方式
- ES3 :
var
- ES6 :
let、const
function
创建函数class
创建一个类import
基于ES6Module
或者Common.js
规范导入模块
JS中变量命名规范
- 严格遵循大小写
- 使用驼峰命名法
- 由有意义英文组成一个名字,第一个单词首字母小写,其余每一个有意义的单词首字母大写
add / insert / create
新增/插入/创建del / delete / remove
删除/移除update
修改select / query / get
查询/获取info
信息
- 由数字、字母、下划线、$组成,并且不能以数字开头
- 基于
$
开头:一般代表使用JQ或者其它使用$
的类库获取的内容 - 基于
_
开头:一般代表是全局或者公共的变量 - 基于数字区分相似名称的变量
- 想要分隔单词,可以使用
_
或者驼峰,但是不能是-
- 基于
- 不能使用关键字和保留字
- 关键字:在JS中有特殊含义的
- 保留字:未来可能会成为关键字的
代码强迫症:良好的编程习惯、极客精神
JS的数据类型
- 基本数据类型(值类型/原始值)
- 数字
number
- 字符串
string
- 布尔
Boolean
- 空对象指针
null
- 未定义
undefined
- ES6新增的唯一值类型
symbol
BigInt
ES6新增的
- 数字
- 引用数据类型
- 对象数据类型
object
- 普通对象
{ }
- 数组对象
[ ]
- 正则对象
/^$/
- 日期对象
new Date
- 数学函数对象
Math
- …
- 普通对象
- 函数数据类型
function
- 对象数据类型
number数据类型
正数、零、负数、小数
NaN:not a number
不是一个有效数字,但是属于number
类型的
Infinity
:无穷大的值,也是number
类型的
1. 验证n是不是有效数字
NaN
和任何数都不相等,包括它本身isNaN
验证一个值是否为非有效数字,如果是有效数字,则返回false
,如果不是有效数字,则返回true
。- 在使用
isNaN
检测的时候,如果被检测的值是非数字类型的值,则需要先把其转化为数字类型,然后再进行检测;
规律:
- 结果不是
false
就是true
- 结合下方的
Number()
方法来记:
Number()
结果为NaN
,isNaN
的结果就是true
;
Number()
结果不为NaN
,isNaN()
结果为false
console.log(1 == 1) //true
console.log(NaN ==NaN) //false
console.log(isNaN(1)); //=>false
console.log(isNaN(NaN)); //=>true
console.log(isNaN(Infinity)); //=>false
console.log(isNaN('AA')); //=>true
console.log(isNaN('12.5')); //=>false
console.log(isNaN('12.5px')); //=>true
console.log(isNaN([])); //=>false
console.log(isNaN([10])); //=>false
console.log(isNaN([10, 20])); //=>true
console.log(isNaN({})); //=>true
console.log(isNaN(null)); //=>false
console.log(isNaN(undefined)); //=>true
console.log(isNaN(Symbol(1))); //=>报错
2. 把其他类型转化为数字类型
Number([value])
parseInt ([value])
parseFloat([value])
3. Number([value]) 转数字
(是JS内置的转换方法,可以把其他数据类型‘强制转换为数字类型’)
- 把字符串转化为数字:一但字符串中出现非有效数字字符,则结果为
NaN
,只有都是有效数字字符,才能转化为具体的数字 - 把布尔转化为数字:
true
为1,false
为0 - 把空转化为数字:
null
为0 ,undefined
为NaN
- 不能把
Symbol()
类型转化为数字,否则会报错 - 对象转化为数字:先把对象转化为字符串,再把字符串转化为数字
-
普通对象(都为
NaN
)- 先把
obj
转化为字符串,'[object Object]'
- 把字符串转化为数字
Number('[object Object]')
- 先把
-
数组对象( 当数组中有2个或者2个以上的时候为
NaN
,)ary = [10];
- 先把
ary
转化为字符串 ‘10’ - 在把’10’转化为10 //10
ary = [10,20];
- 先把
ary
转化为字符串 ‘10,20’ - 在把’10,20’转化为数字 //NaN
- 先把
-
其余对象格式基本上都会变成数字
NaN
-
- 函数转化为数字,结果都是
NaN
规律:
1 、字符串里面有非数字就是NaN
,空字符串为0;true
为1,false
为0,null
为0,undefined
为NaN
.
2、 引用数据类型先变字符串toString()
再转数字
数组变字符串,各项之间使用逗号分隔,整体包起来。因此当数组中长度大于等于2时,结果为NaN
普通对象转字符串都为'[object Object]'
,因此都为NaN
console.log(Number('12')); //=>12
console.log(Number('12.5')); //=>12.5
console.log(Number('12px')); //=>NaN
console.log(Number('12.5.0')); //=>NaN
console.log(Number(true)); //=>1
console.log(Number(false)); //=>0
console.log(Number(null)); //=>0
console.log(Number(undefined)); //=>NaN
console.log(Number(Symbol(13))); //=>Cannot convert a Symbol value to a number
console.log(Number(function func() {})); //NaN
4. parseInt()/parseFloat()
处理原理和Number
不一样,他们是把字符串转化为数字类型(如果处理的值不是字符串,需要先转为字符串然后再去转化为number
类型)
从字符串最左边开始查找,把找到的有效数字字符转化为数字,一直遇到一个非有效数字字符为止,则结束查找
parseInt
不能识别小数点parseFloat
可以识别一位小数点
规律:
当数字开头时:结果为到遇到非数字字符之前的所有值
当不是数字开头时:不管中间有多少个数字,结果都为NaN
引用数据类型变为字符串再查找
console.log(Number('12px')); //=>NaN
console.log(parseInt('12px')); //=>12
console.log(parseInt('12px24')); //=>12
console.log(parseInt('width:12px')); //=>NaN
console.log(parseInt('12.5px')); //=>12
console.log(parseFloat('12.5px')); //=>12.5 parseFloat比parseInt多识别一个小数点
console.log(Number(true)); //=>1
console.log(parseInt(true)); //=>先把TRUE转换为字符串"TRUE" parseInt('true') =>NaN
console.log(parseInt(NaN)); //=>NaN
console.log(Number(null)); //=>0
console.log(parseInt(null)); //=> parseInt('null') =>NaN
console.log(isNaN(Number(parseInt("0.8")))); //=>parseInt("0.8")->0 Number(0)->0 isNaN(0)->false
console.log(Number('')); //=>0
console.log(parseInt('')); //=>NaN
string数据类型
在JS中用 单引号/双引号/反引号 包起来的都是字符串:每一个字符串都是由零到多个字符组成的,和数组类似,每一个字符也都有自己的索引。
str.length
存储了一共有多少个字符,也就是字符串的长度
1. 把其他数据类型转化为字符串类型
String([value])
[value].toString()
其他数据类型转为字符串的规律
- 基本数据类型直接加引号
- 普通对象转为字符串都是
'[object Object]'
- 数组对象转为字符串是’第一项,第二项…’ 逗号分隔数组中的每一项
2. 在JS中常用的数学运算
数学运算:+ - * / %
不管是什么运算,只要有一项转为数字是NaN
,那么结果必定为NaN
- 除了加法以外,其余的情况都是数学运算(如果遇到非数字类型,需要基于
Number
把其强制转换为数字类型,然后再进行运算) - 加号在JS中既有数学运算,也有字符串拼接的意思(只要加号两边的任意一边出现字符串,或者有一边是引用数据类型,则变成字符串拼接)
- 不是数字就先转数字:引用数据类型先转为字符串再转数字,但是当它转为字符串的时候,也就可以拼接了
- 在拼接的时候:基本数据类型直接拼进去,引用数据类型转为字符串再拼进去。
规律:
遇到字符串开始拼接
基本数据类型不用变,直接加进去
引用数据类型变为字符串再加进去
//腾讯的面试题
console.log(100 + true + 21.2 + null + undefined + 'Tencent' + [] + null + 9 + false); // 'NaNTencentnull9false'
console.log(3 - "3px"); //=>NaN
console.log(3 + "3px"); //=>"33px" 字符串拼接
console.log(1 + "1"); //=>"11" 字符串拼接
console.log(1 + {}); //=>"1[object Object]" 在把{}转换为数字过程中,先把他转换为字符串"[object Object]",此时右侧出现了字符串,则不再是数学运算,而是字符串拼接了
console.log(1 + []); //=>'1'
console.log([10] + true); //=>"10true" 在转换[10]到数字的过程中,先把其转换为字符串"10",此时操作变为字符串拼接(和数学运算没关系了)
console.log(true + [10]); //=>"true10"
console.log(1 + true); //=>2
3. 字符串中的方法
字符串中无需记忆原始字符串是否改变,因为它是基本数据类型,每一个操作都是直接操作值,对原始字符串不会产生任何影响(数组之所以要记住是否改变,是因为数组是对象类型,操作的是堆内存,方法的执行很可能把原始堆内存中的信息改变了,所以需要记忆原始数组是否改变)
获取字符串中指定位置字符的办法
charAt([index])
:根据索引获取指定位置的字符(charAt
相对于直接基于索引获取的方式,在当前索引并不存在的情况下,字符串[索引]获取的结果是undefined
,而charAt
获取的结果是空字符串)charCodeAt
:在charAt
的基础上获取指定字符的Unicode
编码String.fromCharCode([unicode编码])
:和charCodeAt
对应,他是基于编码获取编码前的字符
字符串查找和截取
最后的M不写就是截取到字符串的末尾
-
substr(n,m)
:从索引N开始截取M个字符 -
substring(n,m)
:从索引N开始,找到索引为M处(不包含m),找到的部分截取 -
slice(n,m)
:和substring
一样,只不过slice
支持负数索引
slice(-6,-3)
:从倒数第六个索引截取到倒数第三个索引(不包含倒数第三个)
字符串转化为数组的方法
split
:和数组中的join
方法对应,他是把字符串按照指定的分隔符号拆分为数组中的每一项,返回结果是一个数组
- 不指定分隔符时,逐个分隔开来
字符串中查找是否包含某个字符
-
indexOf / lastIndexOf
:获取当前字符在字符串中第一次或者最后一次出现位置的索引。如果字符串中不包含这个字符,那么返回结果是-1 -
includes
:验证是否包含某个字符。true / false
字符串替换
replace(原始字符,新字符)
:把字符串中原始字符替换称为新字符,在不使用正则的情况下,每次执行replace
只能替换一个
字符串大小写转换
toLowerCase
:把字符串中所有的字符转化为小写toUpperCase
:把字符串中所有的字符转化为大写
boolean数据类型
有两个值:true
、false
1. 如何把其他数据类型转化为布尔类型
Boolean([value])
![value]
把指定的值转化为布尔类型后再取反!![value]
取反再取反,相当于没有取反;只是把他转化为布尔类型值
规律:只有 0/NaN/null/undefined/''
最后是false
,其余都是true
console.log(!!-1); //true
console.log(!!0); //false
console.log(!!undefined); //false
console.log(!!Number('12px')); //false
console.log(!![]); //true
console.log(!!''); //false
console.log(!!{}); //true
2. 在条件判断中的应用:
条件判断中,每一个条件最后结果一定是true/false
其中一个值,也就是要把这个值转化为布尔,然后校验程序的真假
if(3 + '3px'){} //true
if(3 - '3px'){} //false
普通对象object
1. 普通对象
- 用键值对(
key:value
俗称属性名和属性值) 来描述一个对象的特征(每一个对象都是综合体,存在零到多组键值对) {key:vlaue,....}
每一组键值对是key:value
的格式,多组键值对之间使用逗号分隔key
不能是引用数据类型value
可以是任何的数据类型
var obj = {
name:'lili',
age:15
};
2. 操作属性的两种方法
- 对象.属性名 = 属性值 : ‘.’ 是‘的’的意思, 这一种获取方式,对象的属性名不能是数字
- 对象[‘属性名’] = 属性值
3. 关于对象中键值对的增删改查
- 新增或者修改属性和属性值
- 对象的属性名是不允许重复的,之前没有这个属性则为新增,之前有这个属性,则是修改对应的属性值
- 获取对象中的属性名和属性值
- 获取指定属性名的属性值
console.log(obj.sex)
console.log(obj['sex'])
- 如果指定的属性不存在,获取到的属性值是
undefined
- 获取当前对象中所有的属性名:返回结果是包含所有属性名的数组
console.log(Object.keys(obj));
- 获取指定属性名的属性值
- 删除对象中指定的属性
- 假删除:当前属性还存在,只不过属性值为空
对象名.属性名 = null
- 真删除:彻底把属性从对象中移除
delete 对象名.属性名
- 假删除:当前属性还存在,只不过属性值为空
4. 对象中的属性名的知识点
- 基于 对象[属性名] 的方式操作,需要保证属性名是一个值(字符串/数字/布尔等都可以),如果不是值而是一个变量,它会把变量存储的值作为对象的属性名进行操作
- 基于 对象.属性名 的方式操作,属性名就是点后面的
如果对象的属性名是一个引用数据类型,那么会去隐性的转为字符串再去操作
let a={}, b={n:'1'}, c={m:'2'};
a[b]='今天';
a[c]='明天';
console.log(a[b]);
obj[ n ] = 100 和 obj [‘n’] = 100的区别
obj[ n ] =100
它是去找变量名是n所指的值- 当变量n不存在时,会报错
Uncaught ReferenceError: n is not defined n
这个变量没有被定义 - 当这个变量存在时,这个变量的值是新增对象中的属性名,属性值是100
- 当变量n不存在时,会报错
obj ['n'] = 100
它是去找这个对象中是否有属性名是n的键值对- 如果没有,结果是
undefined
- 如果有,会修改里面值,把属性名是n的值改为100,(因为对象中的属性名不能重复)
- 如果没有,结果是
let n = 10;
let obj = {}
obj[n] = 200; //这里的是n是变量n ,因此这里是为obj对象加了一个属性名为10,属性值为200的键值对
obj['n'] = 100; //这里的n是属性名
数组对象
1. 数组是特殊的对象
对象都是由键值对组成的,每项之间是有逗号隔开,但是数组是特殊的对象
- 数组中我们看到的每一项都是属性值,默认的属性名是数字,数字从零开始递增,数字代表当前是第几项,我们把代表位置的数字属性称为‘索引’:数组是以数字为索引,索引从零开始递增的结构;
- 默认存在一个
length
属性,代表数组的长度(有多少项) - 数组中存在的每一项可以是任何数据类型
在项目中,我们从服务器获取到的数据,一般都是对象或者数组(JSON格式),而且结构层级一般也都是多级结构,所以学会数组/对象的相关操作,能够根据需求把获取到的数据进行有效的解析和处理,是当下前端开发中非常重要的知识点:尤其是
Vue/reat
开发的时候,我们都是在不断的操作数据,来控制视图的渲染,而操作的数据也是以对象和数组偏多;
2. 数组的维级
- 一维数组
let arr = [10,20,30]
- 二维数组(多维数组)有两级或者多级结构
let arr = [{x:100},10]
3. 数组的内置方法
关于数组的增删改 :原数组都会改变
push:
向数组末尾追加元素
@params:
参数个数不固定,类型也不固定,都是向数组末尾依次追加的内容@return :
新增后数组的长度- 原数组改变
let arr = [10,20]; arr.push(20)
pop :
删除数组中的最后一项
@params:
无@return :
被删除的那一项- 原数组改变
let arr = [10,20]; arr.pop()
unshift:
向数组开头追加元素
@params:
参数不定,类型不定,都是要依次新增的内容@return:
新增后数组的长度- 原数组改变
let arr = [10,20]; arr.unshift(20)
shift:
删除数组的第一项
@params:
无@return:
被删除的那一项- 原数组改变
let arr = [10,20]; arr.shift()
splice:
实现数组指定位置的增删改
arr.splice(n,m):
从数组中索引为n
开始,删除m
个元素,返回结果是以新数组的方式,把删除的内容进行存储(m
不写就是删除到末尾)arr.splice(n,m,x1,x2,...):
从索引n
开始,删除m
个元素,并且使用x
替换删除的内容,返回结果是一个数组,存储删除的内容arr.splice(n,0,x1,x2,...):
从索引n
开始,不删除,把x
的值插入到索引n
的前面
关于数组查询和拼接 : 不会改变原数组
slice:
实现数组的查询
slice(n,m):
从索引n
开始,查找到索引为m
处(不包含m
),把查找到的内容以新数组的方式返回,原数组不变- 第二个参数不写是直接查找到数组末尾
- 可以理解为把原数组中的每一项都查找到,以新数组返回,实现出‘数组的克隆’:得到的新数组和原始数组是两个不同的数组(不同的堆),但是堆内的内容一致
concat:
实现数组的拼接,把多个数组(或者多个值)最后拼接为一个数组,原始的数组都不会变,返回结果是拼接后的新数组
转为字符串:原数组不变
-
tostring:
把数组中的每一项按照‘逗号分隔’,拼接成对应的字符串 -
join:
指定分隔符
arr.join() :
等价于tostring
arr.join('+'):
加号分隔,如果想实现加法:eval(arr.join('+'));
验证是否包含某一项 :原数组不变
indexOf / lastIndexOf:
获取当前项在数组中第一次/最后一次出现位置的索引
- 如果数组中不包含这一项,返回值是-1
includes:
验证数组中是否包含这一项,返回false/true
关于排序的
-
reverse:
把原数组倒过来排列,返回的结果是排列后的原数组,原数组改变 -
sort:
把原数组按照规则进行排序,原数组会改变(返回结果也是改变后的原始数组)
sort
支持传递回调函数,基于自定义的排序规则,进行排序的- 不能处理两位以及两位以上的内容排序
arr.sort(function(a,b){return b - a;})
a - b
升序b - a
降序
关于数组迭代的方法
forEach:
遍历数组的每一项(数组中有多少项,函数会相继被执行多少次)
- 每一次执行函数,都可以在函数中获取到当前遍历的这一项和对应的索引
map:
forEach
是不支持返回值的,而map
可以在forEach
的基础上支持返回值,把原来数组中每一项的值替换为新值,最后存储在一个新的数组中,但是原始数组是不变的
删除数组末尾项
arr.pop();
arr.length--;
arr.splice(arr.length - 1)
向数组末尾追加一项
ary.push(x);
ary[ary.length] = x
ary.splice(ary.length,0,x)
日期对象
Math
Math
作为一个对象数据类型值,在它的堆内存中,存储了很多的内置属性和方法,这些方法一般都是用来操作数字的,所以我们把Math
称为‘数学函数对象’
console.log(typeof Math)
console.log(Math)
Math中的内置方法
Math.PI / Math['PI'] :
获取圆周率 =》 3.141592653589793Math.abs([N]):
获取数字N的绝对值(绝对值都是正数)Math.ceil([N]) / Math.floor([N]) :
把数字N
向上或者向下取整Math.round(N) :
把数字N
四舍五入(结果都是整数)
- 正数中,小数点后面5以及5以上进一位
- 负数中,小数点后面5以及5以下是舍去
Math.max(N1,N2,...) / Math.min(N1,N2,...):
获取一堆数值中的最大值和最小值Math.pow([N],[M]):
获取数字N
的M
次幂Math.sqrt([N]):
给数字N
开平方Math.random():
获取0~1之间的随机小数
- 获取
[N,M]
之间的随机整数(包含N
和M
):Math.round(Math.random()*(m-n) + n)
数据类型的检测(会专门写一个关于数据类型检测的文章来详细说明)
JS中的数据类型检测
typeof [value]
检测数据类型的运算符[example] instanceof [class]
检测某一个实例是否属于这个类[example].constructor === [class]
检测实例和类关系的,从而检测数据类型Object.prototype.toString.call([value])
检测数据类型
typeof [value]
细节点:
- 返回值是字符串,字符串中包含了对应的数据类型
被检测的数据类型 返回值 number ‘number’ string ‘string’ Boolean ‘boolean’ null ‘object’ undefined 'undefined ’ symbol() ‘symbol’ BigInt ‘bigint’ 对象 ‘object’ 函数 ‘function’
特殊的检测结果
NaN / Infinity
都是数字类型,检测出来的结果是'number'
typeof null
的结果是'object'
(这个是浏览器的BUG
:所有的值在计算机中都以二进制编码存储,浏览器把前三位是000的当做对象,而null
的二进制前三位就是000。所以被识别为对象,但是它不是对象,它是空对象指针,是基本数据类型)typeof
普通对象/数组对象/正则…结果都是'object'
,这样就无法基于typeof
区分是普通对象还是数组对象等
console.log(typeof []); //=>"object"
console.log(typeof typeof typeof []); //=>'string'
//由于typeof返回的结果永远是一个字符串(字符串中包含了对应的类型),
//所以连续出现两个及两个以上typeof检测的时候,最后结果都是 "string"
数据类型的比较
==
左右两边数据类型不一致,先默认转化为一致的,再进行比较
===
数据类型 和 值都相等
基于== 进行比较的时候,左右两边数据类型不一致,隐性转换规则
NaN == NaN
=>false
=> 因为NaN
和任何值(包含自己本身)都不相等Infinity == Infinity
=>true
=>Infinity
只和自己相等,和其他值不相等Symbol(1) == Symbol(1)
=>false
- 对象 == 对象 比较的是内存地址
null == undefined
=>true
=>null
和undefined
两个等号比较是等的,三个等号比较是不相等的,除此之外,他们和任何值相比较都不相等- 对象 == 字符串 都转为字符串
正常的比较
- 数字 == 字符串 都转数字
- 数字 == 布尔 都转数字
- 数字== 对象 都转数字
- 字符串 == 布尔 都转数字
- 布尔 == 对象 都转数字
console.log([10] == '10'); //=>'10'=='10' true
console.log({} == '{}'); //=>'[object Object]'=='{}' false
console.log(1 == true); //=>1==1 true
console.log(2 == true); //=>2==1 false
console.log(-1 == false); //=>-1==0 false
console.log(0 == false); //=>0==0 true
console.log(1 == '1'); //=>1==1 true
console.log(true == '1'); //=>1==1 true
console.log(false == ''); //=>0==0 true
console.log([] == 0); //=>0==0 true
总结
这是javascript中的基础知识,想要在这条路上走得更远,基础知识也是需要基础加深印象。
如果觉得写得还不错,请关注我的掘金主页。今后让我们一起成长。