现在的前端框架层出不穷,3个月就要重新入门一次前端的现状,让我们来不及学好基础就开始上手框架。常常就因为这样,我们会很快到达基础
技术瓶颈
,基础是所有技术的核心,在跳槽季重新温故了一遍 javascript 基础,有收获,整理出来分享给大家。
对象
变量可以当对象使用
javascript
中所有的变量都可以当做对象使用,除了undefined
和 null
,我们测试下
|
|
|
|
数值和对象虽然能调用 toString
方法,但是在写法上需要注意下
number
调用时不能直接数值后面直接调用toString
方法,因为 js
会将点运算符解析为数值的小数点
|
|
对象直接调用toString
方法时,需要用小括号包裹起来,不然js
会将对象的花括号识别成块,从而报错
|
|
对象删除属性
删除对象的属性唯一的方法是使用
delete
操作符,设置元素属性为undefined
或则null
并不能真正删除,只是移除了属性和值的关联
|
|
运行结果
|
|
只有 love
被正则删除,name
和 age
还是能被遍历到
构造函数
在
javascript
中,通过关键字new
调用的函数就被认为是构造函数,我们可以通过构造函数创建对象实例
但是在使用过程中你一定发现了,每实例化一个对象,都会在实例对象上创造构造函数的方法和属性。倘若创建的实例比较多,重复创建同一个方法去开辟内存空间就会显得十分浪费,我们可以通过把被经常复用的方法放在原型链上。
原型继承
javascript
和一些我们所了解的面向对象编程的语言不太一样,在es6
语法以前,我们是通过原型链来实现方法和属性的继承
|
|
对象的属性查找,javascript
会在原型链上向上查找属性,直到查到 原型链顶部,所以,属性在原型链的越上端,查找的时间会越长,查找性能和复用属性方面需要开发者自己衡量下。
获取自身对象属性
hasOwnProperty
方法能够判断一个对象是否包含自定义属性,而不是在原型链上的属性
|
|
for in
循环可以遍历对象原型链上的所有属性,如此我们将 hasOwnProperty
结合循环for in
能够获取到对象自定义属性
|
|
除了上面的方法,getOwnPropertyNames
和 Object.keys
方法,能够返回对象自身的所有属性名,也是接受一个对象作为参数,返回一个数组,包含了该对象自身的所有属性名。
|
|
那 getOwnPropertyNames
和 Object.keys
的用法有什么区别呢
Object.keys
方法只返回可枚举的属性,Object.getOwnPropertyNames
方法还返回不可枚举的属性名。
|
|
函数
函数声明的变量提升
我们通常会使用函数声明或函数赋值表达式来定义一个函数,函数声明和变量声明一样都存在提升的情况,函数可以在声明前调用,但是不可以在赋值前调用
函数声明
|
|
函数表达式
|
|
变量提升是在代码解析的时候进行的,foo() 方法调用的时候,已经在解析阶段将 foo 定义过了。赋值语句只在代码运行时才进行,所以在赋值前调用会报错
一种比较少用的函数赋值操作,将命名函数赋值给一个变量,此时的函数名只对函数内部可见
|
|
this 的工作原理
在
javascript
中 ,this
是一个比较难理解的点,不同的调用环境会导致this
的不同指向,但是唯一不变的是this
总是指向一个对象
简单的说,this
就是属性和方法当前所在的对象(函数执行坐在的作用域),平时使用的 this
的情况可以大致分为5种
调用方式 | 指向 |
---|---|
1. 全局范围调用 | 指向 window 全局对象 |
2. 函数调用 | 指向 window 全局变量 |
3. 对象的方法调用 | 指向方法调用的对象 |
4. 构造函数调用 | 指向构造函数创建的实例 |
5. 通过,call ,apply ,bind 显示的指定 this指向 | 和传参有关 |
Function.call
语法:function.call(thisArg, arg1, arg2, …),
thisArg
表示希望函数被调用的作用域,arg1, arg2, …
表示希望被传入函数额参数 , 如果参数为空、null
和undefined
,则默认传入全局对象。
代码示例
|
|
Function.apply
语法和
call
方法类似,不同的是,传入调用函数的参数变成以数组的形式传入,即 func.apply(thisArg, [argsArray])
改造上面的示例就是
|
|
Function.bind
bind
方法用于将函数体内的this
绑定到某个对象,然后返回一个新函数。
|
|
解决方法
|
|
容易出错的地方
容易出错的地方,函数调用,this
总是指向 window
全局变量,所以在对象的方法里如果有函数的调用的话(闭包的情况),this
是会指向 全局对象的,不会指向调用的对象,具体示例如下
|
|
如果需要将 this
指向调用的对象,可以将对象的 this
指向存储起来,通常我们使用 that
变量来做这个存储。改进之后的代码
|
|
####闭包和引用
闭包我们可以理解成是在函数内部定义的函数
在 javascript
中,内部作用域可以访问到外部作用域的变量,但是外部作用域不能访问内部作用域,需要访问的时候,我们需要通过创建闭包,来操作内部变量
|
|
闭包中常会出错的面试题
|
|
很多同学会觉得,上面的代码会正常输出0到9,但是实际是输出十次10。遇到这个题目,除了闭包的概念要理解清楚,你还需要知道,setTimeout
内的代码会被异步执行,代码会先执行所有的同步代码,即上面的这段代码会先将 for
循环执行,此时 i
的值为 10,console.log(i) 一直引用着全局变量的 i 所以会输出十次 10
改进代码,我们在 for
循环里创建一个闭包,把循环自增的 i
作为参数传入
|
|
setTimeout && setInterval
javascript
是异步的单线程运行语言,其他代码运行的时候可能会阻塞setTimeout
&&setInterval
的运行
|
|
处理阻塞的方法是将setTimeout
和 setInterval
放在回调函数里执行
|
|
setTimeout
和 setInterval
被调用时会返回一个 ID 用来清除定时器
手工清除某个定时器
|
|
清楚所有的定时器
|
|
获取最后一个定时器的id,遍历清除定时器,可以清除所有的定时器。
类型
####包装对象
数值、字符串、布尔值——在一定条件下,也会自动转为对象,也就是原始类型的“包装对象”。
我们可以通过构造函数,将原始类型转化为对应的对象即包装对象,从而是原始类型能够方便的调用某些方法
数值,字符串,布尔值的类型转换函数分别是 Number,String,Boolean
,在调用的时候在函数前面加上New 就变成了构造函数,能够蒋对应的原始类型转化为“包装对象”
|
|
类型转换
类型转换分为强制类型转换和自动转换,javascript
是动态类型语言,在到吗解析运行时,需要的数据类型和传入的数据类型不一致的时候,javascript
会进行自动类型转化。当然,你也可以通过类型转换方法进行强制类型装换。
日常开发中,我们最常用的数据类型自动转换不过就下面三种情况
不同数据类型之间相互运算
|
|
对非布尔值进行布尔运算
|
|
对非数据类型使用一元运算符
|
|
我们也通过Number ,String,Boolean
来进行强制数据类型转换。强制类型转化的规则有点复杂,我们来了解一下。
Number 转换 引用阮老师的详细解释
|
|
String
转换方法同样也是通过调用原对象的 toString
方法和 valueOf
方法,但是不同的是 String
函数会先调用 toString
方法进行转换
Boolean
的转换规则会相对简单一些,除了几个特殊的值,都会被转化为 true
|
|
但是要注意
|
|
typeof
typeof
操作符返回数据类型,但是由于javascript
设计的历史原因,typeof
现已经不能满足我们现在对于类型判断的要求了
Value | Class | Type |
---|---|---|
“foo” | String | string |
new String(“foo”) | String | object |
1.2 | Number | number |
new Number(1.2) | Number | object |
true | Boolean | boolean |
new Boolean(true) | Boolean | object |
new Date() | Date | object |
new Error() | Error | object |
[1,2,3] | Array | object |
new Array(1, 2, 3) | Array | object |
new Function(“”) | Function | functio |
/abc/g | RegExp | object (function in Nitro/V8) |
new RegExp(“meow”) | RegExp | object (function in Nitro/V8) |
{} | Object | object |
new Object() | Object | object |
null | null | object |
我们可以看到,typeof
不能区分对象的数组和日期,还会把 null
判断成对象,那我们一般是什么时候用 typeof
呢。我们可以用来判断一个已经定义的变量是否被赋值。
|
|
instanceof
instanceof
操作符通常用来判断,一个对象是否在另一个对象的原型链上,需要注意的是instanceof
的左值是对象,右值是构造函数
|
|
Object.prototype.toString
那么我们有没有可以用来区分变量数据类型的方法呢,有,
Object.prototype.toString
一些原始数据类型也有 toString
方法,但是通常他们的 toString
方法都是改造过的,不能进行 数据类型判断,所以我们需要用 Object
原型链上的 toString
方法
|
|
不同类型返回的结果如下:
|
|
那么我们就能够通过 Object.prototype.toString
方法,封装一个可以判断变量数据类型的函数了
|
|
这次我们从对象、函数、类型三方面入手了解了
javascript
中容易被忽视或则说比较难理解的地方,我会继续将我在学习中积累的内容分享给大家,如果大家觉得文章有需要改进或则有其他想要了解的内容的,欢迎私信,评论或则微信我,我的微信是:646321933