介绍
这是些零散的知识点,整理整理。涉及ES5/ES6/ES7。
1、数据类型 / 转换
JavaScript
默认内置其中数据类型:
6种原始类型:null
,undefined
, boolean
,number
,string
和ES6新出的symbol
;
1种其他类型:object
。
1 | typeof 0 // number |
①对比 null 和 undefined
undefined
表示尚未定义,常作为变量,函数参数,对象属性的默认值。当函数没有返回值时也会默认返回undefined
。null
表示空值,常被赋值给一个变量表示没有值
。
②隐式转换类型
1 | let leo = 'leo' |
此时字符串变量 leo
会被转换成 true
,并执行后面的代码。Falsy
类型的值,指在强制类型转换时会被转成布尔 false
的值。包括: ""
,0
,null
,undefined
,NaN
,false
。
除了 Falsy
类型的值,其他都成为 truthy
类型的值,并转换成 true
。
1 | Boolean(null) // false |
③String 和 Number 转换
+
既可以作为算术运算也可以连接字符串。
但是 *
,/
和-
与字符串一起使用,会强制将字符串转换成数字类型。
1 | 1 + "2" = "12" |
④== 和 ===
==
比较强制类型转换后的结果,而 ===
是直接比较。
1 | 1 == '1' // True |
强制类型转换会造成一些混乱,比如:
1 | let a1 = '0',a2 = false,a3 = 0; |
即:其他类型
与 Boolean
对比,会先把 其他类型
转换成 Boolean类型
再比较;string类型
与 Number
对比,会先把 string类型
转换成 Number类型
再比较;
还有一些特殊的比较:
1 | false == "" // true |
2、函数表达式 和 函数声明
函数表达式只有被执行后才可用,它不会被提升(相当于赋值函数表达式给变量):
1 | let leo = function(a,b){ |
函数声明则可以在定义前后被任意调用,因为它始终会被提升:
1 | function leo(a,b){ |
3、var let const
var
在某一函数内部声明的变量和方法只能在其函数作用域内部访问到。let
所声明的变量,不会被提升,只在 let
命令所在的代码块内有效。const
所声明的变量,不能被重新赋值,但其指向的值是可以被操作的。
1 | function funvar(){ |
4、上下文
上下文的概念经常会同作用域之间混淆。为了保持条理清晰,我们需要注意以下两条:
上下文是在函数被调用时确定的。它通常指的是你的代码当中某一部分的值。
作用域值的则是变量能过被访问到的范围。
1 | // 作用域 |
例如上述实例当中调用 this
的位置不同,this
的指向也是不同的,也就表示着不同的上下文;而作用域则是我们在编写代码时使用 var
关键字来确定的。
5、函数调用方式:call apply bind
这三种方法可以改变函数调用时 this 的指向,区别则在于函数调用的时候。
.call() 会立即调用函数,并要求你按次序一个个传入参数。
.apply() 也会立即调用函数,不过你需要以数组的形式传参。
.call() 和 .apply() 效用几乎是相同的,它们都可以用来调用对象中的某个方法,具体怎么使用取决于你的使用场景里如何传参更方便。
1 | const Snow = {username: 'Snow'} |
注意: 如果你在使用 .call() 时传入了数组形式的参数,它会把整个数组当作一个参数使用。
不过在 ES6 里你倒是可以试试展开操作符的方法进行传参:
1 | char.knows.call(Snow, ...["nothing", "Jon"]); // You know nothing, Jon Snow |
.bind()
不会直接触发某个方法,而是根据你传入的参数和上下文返回一个新的方法。
当你想要在程序之后的某些上下文环境中调用一个方法时可以使用 .bind()
这种方式。
这在我们使用一些异步操作或者事件处理函数时非常有用。.bind()
的传参形式则类似于 .call()
你需要讲参数以逗号分隔传入:
1 | const Snow = {surename: 'Snow'} |
5、严格模式
我们可以通过使用 "use strict"
指令来启用 JavaScript
的严格模式。它会为你的代码添加更多的限制及错误处理。
使用严格模式的好处有:
更方便调试 你能够看到更多的报错,例如在你试图为只读的全局对象或属性赋值时。
防止意外产生全局变量 对未声明的变量进行赋值时会报错。
禁止无效的删除操作 尝试删除变量、函数、不可删除的属性时会报错。
禁止重复的属性名及参数 如果有命名重复的属性名或者参数值就会报错。
让eval()
的调用更加安全 在eval()
方法内部定义的变量及函数不会污染其他作用域。
禁止this
指向全局对象 当this
的值为null
或者undefined
时不会再默认指向到全局对象。这也就意味着在函数内部的this
不会再默认指向window
对象了。
6、Object.keys()
Object.keys()
方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in
循环遍历该对象时返回的顺序一致 (两者的主要区别是 一个 for-in 循环还会枚举其原型链上的属性)。
详细:点击查看
🌰栗子:
1 | /* Array 对象 */ |
7、”void”运算符
查看原文 MDN介绍
这个运算符能向期望一个表达式的值是undefined
的地方插入会产生副作用的表达式。
void 运算符通常只用于获取undefined
的原始值,一般使用void(0)
(等同于void0
)。在上述情况中,也可以使用全局变量undefined
来代替(假定其仍是默认值)。
在MDN上的定义是:void运算符
对给定的表达式进行求值,然后返回undefined
。
使用它来实现立即执行的函数表达式(IIFE
),如下:
1 | void function foo(){ |
使用void
必须注意的是,无论给定表达式返回结果如何,void运算符
整体返回的结果都是空的(undefined
)!
1 | const w1 = void function foo(){ |
与 async
一起使用,这样就能把函数作为异步代码的入口:
1 | void async function (){ |
另外,经常也用在 URI操作
上,当用户点击一个以 javascript: URI
时,它会评估URI中的代码,然后用返回的值替换页面内容,除非返回的值是undefined
。void运算符
可用于返回undefined
。例如:
1 | <a href="javascript:void(0);"> |
注意,虽然这么做是可行的,但利用 javascript:
伪协议来执行 JavaScript
代码是不推荐的,推荐的做法是为链接元素绑定事件。
8、简单介绍闭包
闭包
,又一个老生常谈的话题,可以用一句话对之概括:有权访问另一个函数作用域内变量的函数都是闭包。例如:
1 | function outer(){ |
这里返回的inner函数
就是能够访问outer函数
中变量的闭包,除inner函数
之外的外部作用域都无法访问outer函数
中的变量a
。
闭包特性:
- 1.函数返回嵌套的函数形成闭包
- 2.闭包内部可以访问外部的参数和变量
- 3.外部参数和变量在被闭包引用时不会被垃圾回收机制回收
闭包优点:
- 1.可避免变量对全局的污染
- 2.允许函数私有成员的存在
- 3.允许变量长驻内存
闭包缺点:
由于变量常驻内存,增大内存使用量,使用不当很容易造成内存泄漏。
闭包应用场景:
- 1.采用函数引用方式的setTimeout调用
- 2.将函数关联到对象的实例方法
- 3.封装相关的功能集