--- title: JavaScript 基础语法 date: 2020-10-18 author: ac tags: - JavaScript categories: - Web --- ## JavaScript 基础 ### 变量和数据类型 JavaScript 的变量名区分大小写,A和a是两个不同的变量。声明变量的标识符不能以数字开头,字符集为Unicode。如果一个变量只是声明而没有被赋值,则该变量的值为underfined。 所有的数据都是用var定义。 ```javascript var name = "admin"; var age = 26; var obj = new Date(); ``` > 如果使用var声明一个已经存在的变量,是无效的,但如果并进行了赋值,则会覆盖掉前面的值 > > ES6中新增了let、const 定义变量 **变量提升** JavaScript 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的【声明语句】(var a;),都会被提升到代码的头部,这就叫做变量提升(hoisting) **区块(block)** ```javascript { var a=1; } ``` 区块对于var命令不构成单独的作用域,与不使用区块的情况没有任何区别。 区块通常搭配更复杂的语法结构一起使用如:for、if、while **作用域** ES5中只有两种作用域,全局作用域、函数作用域,ES6中增加了块级作用域。 函数内部定义的变量,会在该作用域内覆盖同名全局变量。 对于var命令来说,局部变量只能在函数内部声明,在其他区块中声明,一律都是全局变量。即函数内部用var声明的变量是局部变量,但像if、switch、for这些{}用var声明的是全局变量。函数执行时所在的作用域,是定义时的作用域,而不是调用时所在的作用域。 **数据类型** number、string、boolean、undefined、null、object - 原始类型:number/string/boolean - 合成类型:object(狭义的对象Object、数组Array、函数function) - 特殊值 :undefined/null typeof元运算符,返回跟在其后面变量的数据类型的字符串。 ```javascript typeof 123 // "number" typeof '123' // "string" typeof false // "boolean" function f() {} typeof f // "function" typeof undefined // "undefined" undefined返回undefined。没有声明的变量也为undefined typeof window // "object" typeof {} // "object" typeof [] // "object" 数组本质上只是一种特殊的对象,instanceof运算符可以区分数组和对象 typeof null // "object" ``` **undefined和null的区别**: - null是一个表示“空”的对象,转为数值时为0; - undefined是一个表示”此处无定义”的原始值,转为数值时为NaN。 ```javascript Number(null) // 0 Number(undefined) // NaN ``` > parseInt逐个解析字符,而Number函数整体转换字符串的类型 **返回undefined的典型场景**: 1. 变量声明了,但没有赋值 2. 调用函数时,应该提供的参数没有提供,该参数等于 undefined 3. 对象没有赋值的属性 4. 函数没有返回值时,默认返回 undefined **隐式布尔型:** 当预期某个位置应该是布尔值,会将该位置上现有的值自动转为布尔值 - "": false,对于任何非空字符串都是 true. - 0: false,对于任何非0数值都是 true. - null: false,对于任何非空对象都是 true. ### 对象 #### Object对象
JS原生提供Object对象,JS中的所有其他对象都继承自Object对象。
> 其他对象指的是调用对象的toString()方法返回"[object Object]"的对象。第二个Object是该对象创建时使用的构造函数,可以是Number、String、Boolean、Undefined、Null、Array、Arguments、Function、Error、Date、RegExp、Object。 本身方法:直接定义在Object对象上的方法。 实例方法:定义在Object原型对象Object.prototype上的方法。 在Object.prototype对象上面的属性和方法,将被所有实例对象共享。 **构造函数与Object()** 作为构造函数使用new关键字创建新的对象。 ```javascript var obj = new Object(); ``` > 通过var obj = new Object()的写法生成新对象,与字面量的写法var obj = {}是等价的。 `Object`本身也是一个函数,Object(arg)将参数arg转为对象,如果参数为空或是undefined和null,则返回空的对象 但Object(value)与new Object(value)两者的语义是不同的: - Object(value)表示将value转成一个对象。 - new Object(value)则表示新生成一个对象,它的值是value。 **静态方法** - Object.keys():方法只返回可枚举(可遍历)的该对象自身(不是继承的)的属性数组。 - Object.getOwnPropertyNames():方法返回该对象自身的属性数组(可遍历和不可遍历的都返回)。 ```javascript var a = ['Hello', 'World']; Object.keys(a) // ["0", "1"] Object.getOwnPropertyNames(a) // ["0", "1", "length"] var obj = {p1: 123,p2: 456}; Object.getOwnPropertyNames(obj) // ["p1", "p2"] ``` - Object.getOwnPropertyDescriptor():获取某个属性的属性描述对象。 - Object.defineProperty():通过描述对象,定义某个属性。 - Object.defineProperties():通过描述对象,定义多个属性。 - Object.create():该方法可以指定原型对象和属性,返回一个新的对象。 - Object.getPrototypeOf():获取对象的Prototype对象。 **实例方法** 方法定义在Object.prototype对象,所有Object的实例对象都继承了这些方法: - Object.prototype.valueOf():返回当前对象对应的值。 - Object.prototype.toString():返回当前对象对应的字符串形式。 - Object.prototype.toLocaleString():返回当前对象对应的本地字符串形式。 - Object.prototype.hasOwnProperty():判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性。 - Object.prototype.isPrototypeOf():判断当前对象是否为另一个对象的原型。 - Object.prototype.propertyIsEnumerable():判断某个属性是否可枚举。 #### 属性描述对象 JavaScript 提供了一个内部数据结构,用来描述对象的属性,控制它的行为,比如该属性是否可写、可遍历等等。每个属性都有自己对应的属性描述对象,保存该属性的一些元信息。 Object中与对象属性相关的静态方法: - `Object.getOwnPropertyDescriptor()`:获取某个属性的描述对象。 - `Object.defineProperty()`:通过描述对象,定义某个属性。 - `Object.defineProperties()`:通过描述对象,定义多个属性。 ```javascript //属性描述对象 { value: 123,//属性值,默认为undefined writable: false,//属性值(value)是否可改变,默认为true enumerable: true,//该属性是否可遍历,默认为true.如果设为false,for...in循环,Object.keys跳过该属性。 configurable: false,//表示可配置性,默认为true get: undefined, set: undefined } var obj = Object.defineProperties({}, { p1: { value: 123, enumerable: true }, p2: { value: 'abc', enumerable: true }, p3: { get: function () { return this.p1 + this.p2 }, enumerable:true, configurable:true } }); obj.p1 // 123 obj.p2 // "abc" obj.p3 // "123abc" //Object.defineProperty(object, propertyName, attributesObject) var obj = Object.defineProperty({}, 'p', { value: 'abc', writable: false,//设为false,该属性不可改变 enumerable: true, configurable: false }); obj.p // 'abc' obj.p = 'ABC'; obj.p // 'abc' ``` > `Object.defineProperty()`和`Object.defineProperties()`参数里面的属性描述对象,`writable`、`configurable`、`enumerable`这三个属性的默认值都为`false Object中与对象状态有关的静态方法: - `Object.preventExtensions()`:防止对象扩展,使得对象无法再添加新的属性。 - `Object.isExtensible()`:判断对象是否可扩展。 - `Object.seal()`:禁止对象配置,使得对象无法添加新的属性,也不能删除旧的属性。 - `Object.isSealed()`:判断一个对象是否可配置。 - `Object.freeze()`:冻结一个对象,使得一个对象无法添加新属性、无法删除旧属性、也无法改变属性的值,使得这个对象实际上变成了常量。 - `Object.isFrozen()`:判断一个对象是否被冻结。 #### JSON对象 `JSON`对象是 JavaScript 的原生对象,用来处理 JSON 格式数据(大括号加键值对的形式)。 拥有两个静态方法: - JSON.stringify方法用于将一个值转为串符合 JSON 格式的字符串; - JSON.parse方法用于将 JSON 字符串转换成对应的值。 通过var obj = new Object()的写法生成新对象,与字面量的写法var obj = {}是等价的。 ```javascript var obj = { "p": 1 }; 'p' in obj // true ``` > in运算符用于检查对象是否包含某个属性,它不能识别哪些属性是对象自身的,哪些属性是继承的,通常与Object的实例方法hasOwnProperty()搭配使用 Object(value)与new Object(value)两者的语义是不同的: - Object(value)表示将value转成一个对象; - new Object(value)则表示新生成一个对象,它的值是value。 对于JSON对象,建议key值用单引号,数字键可以不加因为会自动转为字符串类型但不能用点运算符。 JSON 对值的类型和格式有严格的规定。 1. 复合类型的值只能是数组或对象,不能是函数、正则表达式对象、日期对象。 2. 原始类型的值只有四种:字符串、数值(必须以十进制表示)、布尔值和null(不能使用NaN, Infinity, -Infinity和undefined)。 3. 字符串必须使用双引号表示,不能使用单引号。 4. 对象的键名必须放在双引号里面。 5. 数组或对象最后一个成员的后面,不能加逗号。 **遍历JSON对象** ```javascript var person = { "name": "张三","age": 18 ,"stature": 180}; //for..in会遍历对象所有可遍历(enumerable)的属性,会跳过不可遍历的属性。 for (var key in person) { if (person.hasOwnProperty(key)) { console.log(key); } } //取json对象的方式 person.name person["age"] ``` ### 参考文章 [1] Object对象 `https://wangdoc.com/javascript/stdlib/object.html` [2] 属性描述对象] `https://wangdoc.com/javascript/stdlib/attributes.html` [3] 标准库-JSON对象 `https://javascript.ruanyifeng.com/stdlib/json.html`