1.Javascript基础语法总结
1.JS基本语法使用:
JS 有3种书写位置,分别为行内、内嵌和外部。
行内式:
<input type="button" value="点我试试" onclick="alert('Hello World')" />
内嵌:
<script>alert('Hello World!');</script>
外部:
<script src="my.js"></script>
推荐使用外部方式使用JS,将 JS代码独立到 HTML 页面之外,既美观,也方便文件级别的复用.
2.JS变量声明与提升的机理
函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部。
var声明的提升:
A.var不论在哪里声明的,都会被当成在当前作用域顶部声明的。
B.变量提升是在预编译的过程中发生的,赋值不确定
C.被声明的变量还是在原来的地方,真正被赋值
块级声明:
块级声明用于声明在指定块的作用域之外无法访问的变量。
A.在同一作用域内,相同的标识符只能有一个
B.当执行流离开这个块级,那么这些变量会被销毁
C.块级作用域中的变量会屏蔽串行作用域中的相同标识符的变量(即取的是块级作用域中的值)
D.const不能再赋值,但是可以修改对象的属性值
E.不会变量提升
总结:
let和const是不会变量提升的,所以在声明变量之前,是用typeof是会报错的。因为它存在局部(块)作用域的概念,会出现暂时性死区,所以在它们之前打印变量将报错。
函数声明提升的优先级高于变量声明的提升。浏览器底层的实现过程是这样的:当js解析器在遇到函数声明时,会优先将其提升到定义体顶部,其次再是var声明的变量,这样就导致函数a被变量a给覆盖的情况.
3.JS运算符操作与表达式
表达式:
A.原始表达式:包含常量或直接量、关键字和变量。
B.对象和数组的初始化表达式:包含数组和对象。
C.函数定义表达式:
eg:
var square=function(x){return x*x;}
D.属性访问表达式:运算得到一个对象属性或一个数组元素的值.
eg:
var o={x:1,y:{z:3}}; // 一个包含这个对象的示例数组
o.x //=>1:表达式o的x属性;
o[‘x’] //=>1:对象o的x属性;
a[0].x //=>1:表达式a[0]的x属性
E.调用表达式:一种调用函数或方法的语法表示。函数表达式后跟随一对圆括号,括号内是一个以逗号隔开的参数列表。
eg:
f(0) // f是一个函数表达式,0是一个参数表达式
a.sort() // a.sort是一个函数,它没有参数
F:对象创建表达式:创建对象并调用构造函数初始化对象。最典型的特征就是前边有个new关键字。
eg:
new Point(2,5)
操作符:
A.算术运算符(+, -, *, /, %, **): 普通的加、减、乘、除、取余运算,其中两个乘号为次方运算符。
B.一元运算符(++, --, +, -): 一些只需要一个操作数的运算符,注意:++, --放在变量左右侧的差别,放在变量的左侧是先自增(减),再取值,放在右侧则是先取值,在自增(减)。
C.赋值运算符(=, +=, -=, *=, /=, %=):将某个常量或变量或表达式的值赋值给另一个变量,注意:ES6新增的解构赋值。
//解构数组
let [a, b, c] = [‘one’, ‘two’, ‘three’] // a = ‘one’, b = ‘two’, c = ‘three’
//解构对象
let { name, age } = { name: ‘cc’, age: 100 } // name = ‘cc’, age = 100
D.相等运算符(==; !=):用于比较左右的操作数是否相等。
E:关系运算符(>, <, >=, <=): 用于比较操作符左右的操作数的大小。
F:位操作符(&, |, ~, ^, <<, >>, >>>): 将其操作数转化为二进制后,进行与、或、非、异或等操作运算,最终返回JS中的一个数值。其中>>>为无符号右移。
G:逻辑运算符(&&, ||, !): 主要通过与、或、非来判断一个表达式的值是否为true。注意:与和或操作具有短路计算效果。
H:条件运算符(? :): JS中唯一一个有3个运算数的运算符,一般用于if语句的简短形式来使用。
4.JS基本数据类型和引用数据类型
基本数据类型:
目前常见的有6种:Sting、Number、Boolean、null、undefined、Symbol.基本数据类型保存在栈内存中,因为基本数据类型占用空间小、大小固定,通过按值来访问,属于被频繁使用的数据。
引用数据类型(复杂类型):
Object、Date、function、RegExp、Array …引用数据类型存储在堆内存中,因为引用数据类型占据空间大、占用内存不固定。 如果存储在栈中,将会影响程序运行的性能; 引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。 当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体
下面这张图可以表示这两种数据存储方式不同:
基本数据类型与引用数据类型区别:
基本数据类型存在栈里,引用数据类型在栈里存地址,而在堆里存内容,如果定义数组(对象)m与数组n相等,表示地址相同,所以m与n的指针指向同一个内容,改变内容,则m与n都会改变。
下面这张图可以表示它们之间的区别:
5.JS数据类型检测与转换
基本数据类型的检测(typeof):
基本数据类型中除null外,均可以准确检测。另可以检测Function。
应用:判断变量是引用类型(递归实现深拷贝用到过)
!obj[k] == null && (typeof obj[k] === "object" || typeof obj[k] === "function")
引用类型的检测
- instanceof
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。不能在多全局对象的情况下使用(例如:多个 frame 或多个 window 之间的交互) - Object.prototype.toString.call(myObj) === ‘[object Type]’.Object.prototype上有一个toString()方法,返回一个表示该对象的字符串。判断引用类型和基本数据类型的类型,可以使用该方法.其他构造函数的原型对象继承了该方法,但改写成了输出内容字符串。所以需要用call()修改Object原型上的toString()的this后调用。
- instance.constructor ==(=) Function 或 instance.prote.constructor ==(=) Function
用constructor是可以串联起实例和构造函数的,但是constructor的值是可以被修改的,所以不要这样判断。
数据类型转换:
显式强制类型转换
显示强制类型转换是指代码有明确意图的转换,是显而易见的。主要是使用 Boolean(),Number(),String() 或 Object() 函数,不通过 new 运算符调用这些函数时,会作为类型转换函数进行类型转换。
Number 类的 toString() 方法可以接收并注入和基数的可选参数。如果不知道此参数,转换规则是基于十进制。Number 类的 toFixed() 根据小数点后的指定位将数字转换为字符串。
隐式类型转换:
隐式强制类型转换是指那些隐蔽的,代码在语义上没有明显表明要转换的类型转换。这也是相对的,比如当你看不懂+[]的意思时,它对你来说就是隐式的。 隐式转换最大的好处是代码简洁。
- 如果 “+” 运算符的一个操作数是字符串,它将会把另外一个操作数转换为字符串
- 一元 “+” 运算符将其操作数转换为数字
- 一元 “!” 运算符将其操作数转换为布尔值并取反