ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[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():用于获取给定对象的所有可枚举的自身属性的属性名,它返回一个数组,例子如上