JavaScript语法
❝ECMAscript 的语法大量借鉴了C及其他类C语言的语法;
区分大小写(变量、函数名、操作符)
「标识符:就是指变量、函数、属性的名字,或者函数的参数。」
「标识符定义规则」:「第一个字符必须是一个字母」、「下划线」、或一个「美元符号」,其他字符可以使字母、下划线、美元符$或数字;
「不能把关键字、保留字、true/false和null作为标识符」
采用「驼峰大小写格式」,首字母小写,剩下单词的首字母大写。
❞
严格模式 "use strict" 告诉编译器切换到严格模式
1、变量
❝「变量是松散型」的,就是可以用来保存任何类型的数据。「变量仅仅是」一个用于「保存值的占位符」。
「变量声明的三种方式:」
❞
- 「var 可以用来声明全局变量,也可以声明局部变量」,定义的变量的时候,若没有初始化,不报错,会输出undefined。其值之后可以修改。
- 全局变量:在函数外定义的变量;(注意:若没有使用关键字声明的变量,默认为全局变量。)作用域是整个代码文件。
- 局部变量:在函数内定义的变量。作用域是当前的函数内部。
- 「let 声明块级变量,即局部变量」,函数内部使用let定义后,对函数外部无影响。
- 「const 用于声明常量」,也具有块级作用域 const PI=3.14;且定义的变量不可以修改,而且必须初始化
2、数据类型
❝ES5的时候,我们认知的数据类型确实是 6种:「Number」、「String」、「Boolean」、「Undefined」、「Null」、「Object」。
ES6 中新增了一种 「Symbol」 。这种类型的对象永不相等,即始创建的时候传入相同的值,可以解决属性名冲突的问题,做为标记。
谷歌67版本中还出现了一种 「bigInt」。是指安全存储、操作大整数。(但是很多人不把这个做为一个类型)相关处理大整数的库 bignumber.js
❞
3、typeof 操作符,检测给定变量的数据类型
❝
Type Result Undefined "undefined" Null "object"(see below)Boolean "boolean" Number "number" BigInt (new in ECMAScript 2020) "bigint" String "string" Symbol (new in ECMAScript 2015) "symbol" Function object (implements [[Call]] in ECMA-262 terms) "function" Any other object "object" 「typeof运算符用于判断对象的类型」,但是对于一些创建的对象,它们都会返回'object',有时我们需要判断该实例是否为某个对象的实例,那么这个时候需要用到instanceof运算符,后续记录「instanceof」运算符的相关用法。
「
❞instanceof」 「运算符」用于检测构造函数的prototype属性是否出现在某个实例对象的原型链
3.1 Undefined类型
「只有一个值的数据类型,值即为undefined。」
变量未经初始化的值默认是undefined值。
对未经初始化的变量执行typeof 会返回undefined,对未声明的变量执行typeof也会返回undefined。
「undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。」
3.2 Null 类型
「第二个只有一个值的数据类型,值为null。」
「null值表示一个空对象指针」。这是typeof 返回object的原因。
如果定义的变量准备用于保存对象,一般将变量的初始化值为null。
「null表示"没有对象",即该处不应该有值」
undefined == null // true
undefined === null // false
Number(null) // 0
Number(undefined) // NaN
3.3 Number 类型
❝数值的转换:
非数值转数值:Number()、parseInt()、parseFloat()
parseFloat()是将字符串转换为浮点数,并返回字符串中的数字,直到它到达不是数字部分。
parseInt()可以将任何进制的字符串转换成整数。
❞
// 面试题
[1,2,3].map(parseInt)的结果是什么?
// 首先map的时候,里面传一个函数,那么map会默认给函数传两个参数:value,index,那么这两个参数传给parseInt的时候,代表的意思就不一样了,parseInt函数接收两个参数第一个是要转换的字符串,第二个是代表的按几进制进行转换,注意:是按几进制进行转换,而不是转成了几进制。
// [1,2,3].map(parseInt)
第一次循环,传给parseInt(1,0),把1按0进制转换,0默认表示10进制,然后输出1。
第二次循环,传给parseInt(2,1),把2按1进制转换,引擎懵逼了,1进制中根本不可能出现2这个数字好吗?我咋给你解析,无法解析,给了个NaN。
第三次循环,传给parseInt(3,2),把3按2进制转换,引擎又懵逼了,啥玩意儿?2进制中根本不可能出现3这个数字好吗?我咋给你解析,无法解析,又给了个NaN。
3.4 String 类型
❝由0个或多个16位Unicode字符组成的字符序列,称为字符串。
字符字面量:转义字符 \n 换行 \t 制表 \r 回车
转换字符串:
❞
- toString(x) null和undefined 没有这个方法.;x参数为转换基数。默认是10
- String() 在不知道要转换的值不是null和undefined时,用String()
- +"字符串"
3.5 Object 类型
❝对象其实就是一组数据和功能的集合。
object实列对象都具有下列属性和方法:
- constructor:保存着用于创建当前对象的函数,如构造函数就是Object();
- hasOwnProperty:检查给定的属性是否在当前实列中存在,而不是在实列的原型中存在;
- isPrototypeof(object): 检查传入的对象是否是当前对象的原型
- toLocaleString(): 返回对象的字符串表示,该字符串和执行环境的地区对应
- toString():返回对象的字符串表示
- valueOf():返回对象的字符串、数值、布尔值表示
Object构造函数,会根据给定的参数创建对象,具体有以下情况:❞
- 如果给定值是
null或undefined,将会创建并返回一个空对象- 如果传进去的是一个「基本类型的值,则会构造其包装类型的对象」
- 如果传进去的是「引用类型」的值,仍然会返回这个值,经他们「复制的变量保有和源对象相同的引用地址」
4.操作符
4.1 一元操作符
❝前置型 ++ -- 执行前置递增和递减操作时,变量的值都是在语句被求值前改变。求值前,先执行
后置型 ++ -- 执行后置递增和递减操作时,变量的值都是在语句被求值后改变,求值后,再执行
❞
4.2 布尔操作符
❝非 与 或
「逻辑非 !」
- 将一个值转为与其对应的布尔值,同时使用两个逻辑非!!实际会模拟Boolean()转型函数的行为。第一个!返回一个布尔值,第二!对返回的布尔值进行求反操作。
「逻辑与 &&」
- 两个同时为true才为true
- 第一个操作数能够觉得结果,就不会对第二个操作数操作求值
- 如果第一个操作数是flase,则无论第二个操作数是什么值,都不会返回true
- 两个值都是对象,则返回第二个对象
「逻辑或 ||」
❞
- 只要其中一个为true,则为true
- 如果第一个操作数的求值结果为true,就不会对第二个操作数求值
4.3 相等操作符
❝相等和不相等 == != 都会先转换操作数 强制转换,然后比较他们的相等性
全等和不全等 === == 全等是在两个操作数没转换就相等的情况下返回true
null == undefined // true
null === undefined // false 是不同的类型
❞
5、语句
❝「if」
「do-while」
「while」
「for」
「for-in」
「break continue」 虽然也是立即退出循环,但退出循环后会从循环的顶部继续执行
「Switch1」
❞
6、函数
❝通过函数可以封装任意多条语句,可以在任何地方,任何时候进行调用执行
用「function 关键字声明」,后「跟一组参数」以及「函数体」
「函数本身不运行」,必须调用才运行。
❞
6.1 参数arguments 对象
❝「arguments」 对象与数组类似的对象。
arguments.length 属性可以获知有多少个参数传递给了函数
❞

小结:
❝「1.JS 的数据类型有几种?」
8种。「Number」、「String」、「Boolean」、「Null」、「Undefined」、「Object」、「Symbol」、「BigInt」。
「2.JS的基本类型和引用类型有哪些呢?」
基本类型:除Object。 String、Number、boolean、null、undefined。
引用类型:「Object」。里面包含的 function、Array、Date。
NaN 是 Number 中的一种,非Number 。「typeof NaN // number」
「3.null 和 undefined 有什么区别?」
null表示"没有对象",即该处不应该有值。
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义「简单值例如字符串和数字比较值就可以了」
「对象比较的时候比较的是引用(就是内存地址)」
❞
function deepCompare(x, y) {
var i, l, leftChain, rightChain;
function compare2Objects(x, y) {
var p;
// remember that NaN === NaN returns false
// and isNaN(undefined) returns true
if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') {
return true;
}
// Compare primitives and functions.
// Check if both arguments link to the same object.
// Especially useful on the step where we compare prototypes
if (x === y) {
return true;
}
// Works in case when functions are created in constructor.
// Comparing dates is a common scenario. Another built-ins?
// We can even handle functions passed across iframes
if ((typeof x === 'function' && typeof y === 'function') ||
(x instanceof Date && y instanceof Date) ||
(x instanceof RegExp && y instanceof RegExp) ||
(x instanceof String && y instanceof String) ||
(x instanceof Number && y instanceof Number)) {
return x.toString() === y.toString();
}
// At last checking prototypes as good as we can
if (!(x instanceof Object && y instanceof Object)) {
return false;
}
if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) {
return false;
}
if (x.constructor !== y.constructor) {
return false;
}
if (x.prototype !== y.prototype) {
return false;
}
// Check for infinitive linking loops
if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) {
return false;
}
// Quick checking of one object being a subset of another.
// todo: cache the structure of arguments[0] for performance
for (p in y) {
if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
return false;
} else if (typeof y[p] !== typeof x[p]) {
return false;
}
}
for (p in x) {
if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
return false;
} else if (typeof y[p] !== typeof x[p]) {
return false;
}
switch (typeof(x[p])) {
case 'object':
case 'function':
leftChain.push(x);
rightChain.push(y);
if (!compare2Objects(x[p], y[p])) {
return false;
}
leftChain.pop();
rightChain.pop();
break;
default:
if (x[p] !== y[p]) {
return false;
}
break;
}
}
return true;
}
if (arguments.length < 1) {
return true; //Die silently? Don't know how to handle such case, please help...
// throw "Need two or more arguments to compare";
}
for (i = 1, l = arguments.length; i < l; i++) {
leftChain = []; //Todo: this can be cached
rightChain = [];
if (!compare2Objects(arguments[0], arguments[i])) {
return false;
}
}
return true;
}
本文使用 mdnice 排版