[TOC]
# 基本概念
7 种数据类型: `Null、Undefined、Number、Boolean、String、Object、Symbol`
排除 Symbol 的话,《JavaScript 高级程序设计》中将 Undefined、Null、Number、Boolean、String 定义为基本数据类型,因为其是按值访问的,可以操作保存在变量中的实际的值。引用类型值是保存在内存中的对象,操作对象时,实际上操作的是对象的引用。
[链接:js 中的值类型和引用类型的区别](https://www.cnblogs.com/leiting/p/8081413.html)
如何判断变量的数据类型?
使用`typeof`运算符:
* typeof 对于基本类型,除了 null 都可以显示正确的类型
* typeof 对于对象,除了函数都会显示 object
* 对于 null 来说,虽然它是基本类型,但是会显示 object,这是一个存在很久了的 Bug
```javaScript
typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof b // b没有声明,但是还会显示undefined
typeof [] // 'object'
typeof {} // 'object'
typeof console.log // 'function'
typeof null // 'object'
```
使用`Object.prototype.toString.call()`,该方法返回类似`[object Type]`形式的字符串
```javaScript
let a = []
let b = {}
let c = true
let d = 'string'
let e = null
let f = undefined
let g = 1
let h = function () {}
let i = Symbol('symbol')
console.log(Object.prototype.toString.call(a)) // [object Array]
console.log(Object.prototype.toString.call(b)) // [object Object]
console.log(Object.prototype.toString.call(c)) // [object Boolean]
console.log(Object.prototype.toString.call(d)) // [object String]
console.log(Object.prototype.toString.call(e)) // [object Null]
console.log(Object.prototype.toString.call(f)) // [object Undefined]
console.log(Object.prototype.toString.call(g)) // [object Number]
console.log(Object.prototype.toString.call(h)) // [object Function]
console.log(Object.prototype.toString.call(i)) // [object Symbol]
console.log('[object Array]' === Object.prototype.toString.call(a)) // true
```
## if 条件判断时的注意事项
| 数据类型 | 转换为 true 的值 | 转换为 false 的值 |
| --- | --- | --- |
| Boolean | true | false |
| String | 任何非空字符串 | "" (空字符串) |
| Number| 任何非零数字值(包括无穷大) | 0 和 NaN |
| Object| 任何对象 | null |
| Undefined| N/A(不适用) | undefined |
## 逻辑非
- 如果操作数是一个对象,返回 false
- 如果操作数是一个空字符串,返回 true
- 如果操作数是一个非空字符串,返回 false
- 如果操作数是数值 0,返回 true
- 如果操作数是任意非 0 的值(包括 Infinity),返回 false
- 如果操作数是 null,返回 true
- 如果操作数是 NaN,返回 true
- 如果操作数是 undefined,返回 true
## 四则运算注意事项
只有当**加法运算**时,其中一方是字符串类型,就会把另一个也转为字符串类型。其他运算只要其中一方是数字,那么另一方就转为数字。并且加法运算会触发三种类型转换:将值转换为原始值,转换为数字,转换为字符串。
``` js
1 + '1' // '11'
2 * '2' // 4
[1, 2] + [2, 1] // '1,22,1'
// [1, 2].toString() -> '1,2'
// [2, 1].toString() -> '2,1'
// '1,2' + '2,1' = '1,22,1'
```
对于加号需要注意这个表达式`'a' + + 'b'`
```js
'a' + + 'b' // -> "aNaN"
// 因为 + 'b' -> NaN
// 你也许在一些代码中看到过 + '1' -> 1
```
## toString() 方法的使用
数值、布尔值、对象和字符串值(没错,每个字符串也都有一个 toString() 方法,该方法返回字符串的一个副本)都有 toString() 方法。但 null 和 undefined 值没有这个方法。
多数情况下,调用 toString() 方法不必传递参数。但是,在调用数值的 toString() 方法时,可以传递一个参数:输出数值的基数。默认情况下,toString() 方法以十进制格式返回数值的字符串表示。而通过传递基数,toString() 可以输出以二进制、八进制、十六进制,乃至其他任意有效进制格式表示的字符串值。下面给出几个例子:
```js
var num = 10
alert(num.toString()) // "10"
alert(num.toString(2)) // "1010"
alert(num.toString(8)) // "12"
alert(num.toString(10)) // "10"
alert(num.toString(16)) // "a"
```
# 变量、函数提升
在生成执行上下文时,会有两个阶段。第一个阶段是创建的阶段,JS 解释器会找出需要提升的变量和函数,并且给他们提前在内存中开辟好空间,函数的话会将整个函数存入内存中,变量只声明并且赋值为 undefined。在第二个阶段,也就是代码执行阶段,我们可以直接提前使用。**在提升的过程中,相同的函数会覆盖上一个函数,并且函数优先于变量提升**
简而言之:由于变量提升,使用 var 声明的变量声明前使用则值为 undefined(本作用域下),函数可以在声明之前就使用。
``` javaScript
b() // call b
console.log(a) // undefined
var a = 'Hello world'
function b() {
console.log('call b')
}
var b = 'I am a var'
```
如果你想深入了解这一过程,可以 [点击这里](https://www.kancloud.cn/book/chenmk/web-knowledges/edit)
# instanceof
instanceof 运算符用于测试构造函数的 prototype 属性是否出现在对象的原型链中的任何位置
用法:`对象 instanceof 构造函数`
```javaScript
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
var auto = new Car('Honda', 'Accord', 1998);
console.log(auto instanceof Car);
// expected output: true
console.log(auto instanceof Object);
// expected output: true
```
# Object 对象
参考:[https://www.jb51.net/article/80177.htm](https://www.jb51.net/article/80177.htm)
**对象实例的一些方法**
- hasOwnProperty(propertyName):接收一个字符串参数,该参数表示属性名称,用来判断该属性是否在当前对象实例中,而不是在对象的原型链中。
```
var arr = []
console.log(arr.hasOwnProperty("length")) // true
console.log(arr.hasOwnProperty("hasOwnProperty")) // false
// length 是 arr 自己的属性,而 hasOwnProperty 是原型链上的属性(方法)
```
- isPrototypeOf(Object):isPrototype 方法接收一个对象,用来判断当前对象是否在传入的参数对象的原型链上。关于原型链可参考原型与继承章节。
```
function MyObject() {}
var obj = new MyObject()
console.log(Object.prototype.isPrototypeOf(obj)) // true
```
- toString():返对象的字符串表示
- valueOf():返回对象的原始值,可能是字符串、数值、bool 值等,看具体的对象
**特性操作的相关方法:**
- Object.defineProperty(obj, propName, descriptor):接收三个参数,obj 是需要定义属性的对象,propName 是需要被定义 / 修改的属性名,descriptor 是属性描述符,包含一些属性的特性定义
```
var obj = {}
Object.defineProperty(obj, "name", {
value: "name", // 该属性的数据值,默认为 undefined
configurable: true, // 表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性,默认为 true
writable: true, // 表示能否修改属性的值,默认为 true
enumerable: true, // 表示能否通过 for-in 循环返回属性,默认为 true
get: function () {}, // 访问器属性,在读取属性时调用的函数,默认为 undefined
set: function () {} // 访问器属性,在写入属性时调用的函数,默认为 undefined
})
```
- Object.defineProperties():与 defineProperty 不同之处在于可以同时定义多个属性
```
var obj = {};
Object.defineProperty(obj, {
"name": {
value: "name",
configurable: true,
writable: true,
enumerable: true
},
"age": {
value: 20
}
})
```
- Object.getOwnPropertyDescriptor(obj, propName):用于读取特性值,接收对象及其属性名两个参数,返回一个对象
```
var person = {
_age: 10,
type: "小孩"
}
Object.defineProperty(person, "age", {
get: function () {
return this._age
},
set: function (newValue) {
this._age = newValue
this.type = newValue > 17 ? "成人" : "小孩"
}
})
console.log(Object.getOwnPropertyDescriptor(person, "type"))
// Object {value: "成人", writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(person, "age"))
// Object {enumerable: false, configurable: false, get: function(),set: function ()}
```
**其他:**
- Object.getOwnPropertyNames():用于获取对象自身的所有属性,包括可枚举和不可枚举的所有属性,返回一个数组
```
function Parent() {
this.lastName = "Black"
}
function Child(firstName) {
this.firstName = firstName
}
Child.prototype = new Parent()
var son = new Child("Jack");
Object.defineProperty(son, "age", {
enumerable: false
})
console.log(Object.keys(son)) // ["firstName"]
console.log(Object.getOwnPropertyNames(son)) // ["firstName", "age"]
```
- Object.keys():用于获取给定对象的所有可枚举的自身属性的属性名,它返回一个数组,例子如上
- 序言 & 更新日志
- H5
- Canvas
- 序言
- Part1-直线、矩形、多边形
- Part2-曲线图形
- Part3-线条操作
- Part4-文本操作
- Part5-图像操作
- Part6-变形操作
- Part7-像素操作
- Part8-渐变与阴影
- Part9-路径与状态
- Part10-物理动画
- Part11-边界检测
- Part12-碰撞检测
- Part13-用户交互
- Part14-高级动画
- CSS
- SCSS
- codePen
- 速查表
- 面试题
- 《CSS Secrets》
- SVG
- 移动端适配
- 滤镜(filter)的使用
- JS
- 基础概念
- 作用域、作用域链、闭包
- this
- 原型与继承
- 数组、字符串、Map、Set方法整理
- 垃圾回收机制
- DOM
- BOM
- 事件循环
- 严格模式
- 正则表达式
- ES6部分
- 设计模式
- AJAX
- 模块化
- 读冴羽博客笔记
- 第一部分总结-深入JS系列
- 第二部分总结-专题系列
- 第三部分总结-ES6系列
- 网络请求中的数据类型
- 事件
- 表单
- 函数式编程
- Tips
- JS-Coding
- Framework
- Vue
- 书写规范
- 基础
- vue-router & vuex
- 深入浅出 Vue
- 响应式原理及其他
- new Vue 发生了什么
- 组件化
- 编译流程
- Vue Router
- Vuex
- 前端路由的简单实现
- React
- 基础
- 书写规范
- Redux & react-router
- immutable.js
- CSS 管理
- React 16新特性-Fiber 与 Hook
- 《深入浅出React和Redux》笔记
- 前半部分
- 后半部分
- react-transition-group
- Vue 与 React 的对比
- 工程化与架构
- Hybird
- React Native
- 新手上路
- 内置组件
- 常用插件
- 问题记录
- Echarts
- 基础
- Electron
- 序言
- 配置 Electron 开发环境 & 基础概念
- React + TypeScript 仿 Antd
- TypeScript 基础
- 样式设计
- 组件测试
- 图标解决方案
- Algorithm
- 排序算法及常见问题
- 剑指 offer
- 动态规划
- DataStruct
- 概述
- 树
- 链表
- Network
- Performance
- Webpack
- PWA
- Browser
- Safety
- 微信小程序
- mpvue 课程实战记录
- 服务器
- 操作系统基础知识
- Linux
- Nginx
- redis
- node.js
- 基础及原生模块
- express框架
- node.js操作数据库
- 《深入浅出 node.js》笔记
- 前半部分
- 后半部分
- 数据库
- SQL
- 面试题收集
- 智力题
- 面试题精选1
- 面试题精选2
- 问答篇
- Other
- markdown 书写
- Git
- LaTex 常用命令