运算符
数学运算:+ - * / %
因为JavaScript中只有数字类型,不区分整型和浮点型
-* / % 全部会触发隐式转换,不能转就转成NaN
1、数字运算的加法
除去字符串的情况,其他类型相加都是数字运算
可能会触发隐式转换
2、字符串的拼接
任何类型只要跟字符串相加都是字符串的拼接
NaN (not a number)属于一个特殊的数字,因为是数字类型
转换:
隐式转换
true转换成1
false转换成0
nudefined转换成NaN
null转换成0
强制(显示)转换 能转就转,不能转就转成NaN
parseInt()
字符串类型的小数会舍弃小数部分并转换成数字类型
如果以数字开头,里面含有字符,会截取前面数字部分转换成数字类型
parseFloat()
Number()
只能进行纯数字的字符串转换
逻辑运算
&& || !
赋值运算符
+= -= *= /=
前++ 存储新值,使用新值
后++ 存储新值,使用旧值
作用域,作用域链,闭包,原型,原型链
JavaScript中非常重要的两条链
作用域链:从上往下查找
原型链:从下往上查找
特点:逐行执行 沿着作用域里面的内容来进行逐行执行
1、基本的语法检测 例如单词拼写错误,中文没注释…低级错误
2、形成作用域(对象)的过程,预解析(预编译)
2.1 函数在执行的前的一瞬间会生成一个AO(active object 活动对象)对象
2.2 分析参数,形参作为AO对象的属性名,实参作为AO对象的属性值
2.3 分析var声明,变量名作为AO对象的属性名,值为undefined,如果遇到同名,不会对AO对象做任何改变
2.4 分析函数声明,函数名作为AO的属性名,值为函数体,如果遇到同名,直接以函数声明为主,直接覆盖
3、逐行执行,就是根据预解析的产生出来的对象进行逐行执行
因为JavaScript中只有全局作用域和函数作用域
在进行预解析的时候 只需要去管函数 if判断中的声明(变量声明及函数声明都得正常分析)if条件决定是后面的执行过程
注: var声明是没有影响的,但是函数声明存在兼容性问题(各个版本的浏览器产生的结果会不一样)
1、什么是作用域
作用域就是一个独立的地盘,让变量不会外泄,暴露不去。也就是说作用域最大的用处就是隔离变量,不同作用域下同名变量不会又冲突。
2、全局作用域和函数作用域
在代码中任何地方都能访问到的对象拥有全局作用域,一般来说以下几种情形拥有全局作用域:
最外层函数 和在最外层函数外面定义的变量拥有全局作用域
var outVariable = “我是最外层变量”; //最外层变量
function outFun() {
var inVariable = “内层变量”;
function innerFun() {
console.log(inVariable);
}
innerFun();
}
console.log(outVariable); //我是最外层变量
outFun(); //内层变量
console.log(inVariable); //inVariable is not defined
innerFun(); //innerFun is not defined
所有未定义直接赋值的变量自动声明为拥有全局作用域
function outFun2() {
variable = “未定义直接赋值的变量”;
var inVariable2 = “内层变量2”;
}
outFun2(); //要先执行这个函数,否则根本不知道里面是啥
console.log(variable); //未定义直接赋值的变量
console.log(inVariable2); //inVariable2 is not defined
所有window对象的属性拥有全局作用域
全局作用域有个弊端:如果我们写了很多行 JS 代码,变量定义都没有用函数包括,那么它们就全部都在全局作用域中。这样就会 污染全局命名空间, 容易引起命名冲突。
函数作用域,是指声明在函数内部的变量,和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部。
作用域是分层的,内层作用域可以访问外层作用域的变量,反之则不行
1是全局作用域,有标识符 foo;
2是作用域foo,有标识符a, bar, b;
3是作用域bar,仅有标识符c。
值得注意的是:块元素(大括号“{ }”中间的语句),如 if 和 switch 循环语句,不想函数,他们不会创建一个新的作用域。在块语句中定义的变量将保留在他们已经存在的作用域中。
if(true) {
// ‘if’ 条件语句块不会创建一个新的作用域
var name = “bob”; //name 依然在全局作用域中
}
console.log(name); // logs ‘bob’
3、块级作用域
块级作用域可通过新增命令 let 和 const 声明,所声明的变量在指定块的作用域外无法被访问。块级作用域在如下情况被创建:
在一个函数内部
在一个代码快(由一对花括号包裹)内部
let声明的语法与 var 的语法一致,你基本上可以用 let 来代替 var 进行变量声明,但会将变量的作用域限制在当前代码块中。块级作用域有以下几个特点:
函数声明及函数表达式
区别:
使用:没有任何区别
对预解析有影响的
本质:函数声明式函数,函数表达式是声明的变量
区分:函数声明是以function开头,其他的全是函数表达式
1、一旦函数声明变成了函数表达式,就会放弃函数名(只能看,没有任何作用),函数表达式一般都是没有函数名的
var abc = function fun(){
console.log(‘hello’)
}
function fun (a,b,c){
console.log(‘hello’)
}
fun()
console.log(fun.name) // 函数的名字 fun
//函数是引用类型,函数也是一个对象,函数对象,对象就有自己
console.log(fun.length) // 形参的个数 3
立即执行函数
var a = 10; //加分号
(function(){
console.log(‘hello’);
})();
!function(){
}
()执行符号
不能去直接执行函数声明
可以去执行函数表达式
面试题
// 控制台显示什么内容
function fun(a, b, c, d){
console.log(a + b + c + d)
}(1,2,3,4)
全局作用域
全局作用域,对应的对象是GO(global object),进入script标签以后,在所有代码之前会产生
产生的方式可以说跟AO完全相同,只少了参数这一个步骤
2.1 在进入script标签,的一瞬间会产生一个GO(global object 活动对象)对象
2.3 分析var声明,变量名作为GO对象的属性名,值为undefined,如果遇到同名,不会对AO对象做任何改变
2.4 分析函数声明,函数名作为GO的属性名,值为函数体,如果遇到同名,直接覆盖
一般情况下,变量取值到 创建 这个变量 的函数的作用域中取值。
但是如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链。
闭包:通过一些方式可以访问到函数内部的变量的
正常来说,函数执行完成之后,会销毁
优点:可以变量的安全
缺点:但是闭包会带着父级的作用域保存到外面,导致函数执行完成以后内存不会被释放