const :
定义变量不可更改;
定义对象可更改、扩展、删除对象属性值,仅仅能做到不可更改引用(重新赋值)而已。
实现常量对象:不可更改、扩展、删除属性值。
1.不可扩展: Object.preventExtensions(Obj);
2.1+不可删除: Object.seal(Obj);
3.1+2+不可更改: Object.freeze(Obj);
作用域、作用域链与闭包:
作用域:在 JavaScript 中,作用域为可访问变量、函数与对象的集合。
由于函数是静态作用域 ,函数的作用域在函数定义时就已经决定了。
- 全局作用域——全局变量
- 全局变量属于 window 对象
- 局部作用域——局部变量
- 可称为函数作用域——JavaScript 没有块级作用域
- 若函数内部声明变量时未用 var,则声明的是全局变量
- 变量提升——函数内部定义的局部变量会在解析时提前声明(各大面试爱考点)
作用域链:根据子函数可以访问父函数变量的机制,利用链式查找,找出子函数能访问的变量、函数与对象的集合。
闭包:父函数销毁后,子函数能访问的外部变量仍然保存在内存中。
Exp.1 不符合期望的输出
function outer(){ //外部函数
var r = new Array();
for (var i=0; i<2; i++){
r[i] = function() { //内部函数
console.log(i);
}
}
return r;
}
var fn = outer();
fn[0](); //打印2而不是0
fn[1](); //打印2而不是1
原因为:变量 i 是 fn 函数数组的共同父函数中的变量,在父函数执行完毕后,i 的值已被修改为2,然后再被打印出来。
改进1:符合期望的输出
function outer(){
var r = new Array();
for (var i=0; i<2; i++){
function inner(i) { //内部函数
return function(){
console.log(i);
}
}
r[i] = inner(i);
}
return r;
}
var fn = outer();
fn[0](); //打印0
fn[1](); //打印1
原因为:函数 inner
中的 i
是其局部变量,fn
函数数组分别执行时,调用的是自己的局部变量 i
,该值是在 outer
运行生成 r[i]
时就已经保存好的。
实际上 inner
中的 i
换成任何变量名都可顺利运行,这里这么设置更加 trick。
改进2:符合期望的输出
function outer(){ //外部函数
var r = new Array();
for (let i=0; i<2; i++){
r[i] = function() { //内部函数
console.log(i);
}
}
return r;
}
var fn = outer();
fn[0](); //打印0
fn[1](); //打印1
原因:将源代码声明 i
的 var
改成了 let
。
let
允许你声明一个作用域被限制在块级中的变量、语句或者表达式。let
声明的变量只在其声明的块或子块中可用,而var
声明的变量的作用域是声明它的封闭函数中。
事件循环
含义:因为 js 是单线程运行的,所以异步操作会交给浏览器别的模块来处理,处理完后回调函数会放入任务队列中,等待调用栈清空后再执行该队列。
在程序运行过程中,js 会一直执行轮询任务队列。
参考深入浅出JavaScript事件循环机制(下),事件队列也是有分类的:
macro-task(宏任务)包括:script(整体代码),setTimeout,setInterval,setImmediate,I/O,UI rendering。
micro-task(微任务)包括:process.nextTick,Promises,Object.observe,MutationObserver。
执行顺序是先执行调用栈,再执行微任务,再执行宏任务,然后再回去轮询微任务,一直这么循环。
应用1:setTimeout()
for(var i=0;i<99;i++){
setTimeout(function(){
console.log("two");
},0);
console.log("one");
}
该程序运行结果为先输出99个“one”,再把99个“two”全部输出。因为调用栈总是最先执行。
应用2:Promise
setTimeout(function(){ console.log(5);},0);
new Promise (function(resolve){
console.log(1);
resolve();
}).then(function(){
console.log(3);
}).then(function(){
console.log(4);
});
console.log(2);
该程序输出 1 2 3 4 5。
JS常用对象及其主要方法与属性
1. Number
- 主要方法
- toString(16|8|2)
- toFixed(n)
- toPrecision(n)
- toExponential()
- 属性
- Number.MAX_VALUE
- Number.MIN_VALUE
- Number.NEGATIVE_INFINITY
- Number.POSITIVE_INFINITY
- Number.NaN
- prototype
- constructor
- 特性
- 数字可以是 Number 类型,也可以是 Object 类型。
- js中所有数字都是浮点类型。
2. String
- 主要方法
- charAt(index)
- charCodeAt(index)
- concat(str2)
- search(subs)
- indexOf(subs)
- lastIndexOf(subs)
- match(subs)
- replace(subs, replacement)
- slice(startPos, endPos)
- substring(startPos, endPos(>0))
- substr(startPos, length)
- split()
- toUpperCase()/toLowerCase()
- String.fromCharCode(ASCII)
- 属性
- prototype
- constructor
- length
- 特性
- 字符串可以是 String 类型,也可以是 Object 类型。
- 单目运算符对由数字组成的 String 类型进行运算,会将String 类转为 Number 类。双目运算符除了“+”,两个由数字组成的字符串相加减基本都会有隐式转换。
- 以上方法皆不改变字符串本身。
3. Array
- 主要方法
- join(separator)
- concat(arr2)
- pop()
- push(x)
- shift()
- unshift(x)
- toString()
- toLocaleString()
- slice(startPos, endPos)
- ------以下方法改动原数组本身------
- splice(deleteStart, deleteStop, insert1,insert2,...)
- reverse()
- sort()
- 属性
- 同String
- 特性
- Array可用数组长度或数组元素初始化。
上表输出结果格式为:原始a->函数返回值->结果a。
4. Boolean
- 主要方法
- toString()
- 属性
- constructor
- prototype
- 特性
- Boolean类型可直接与Number类型数据作运算。届时true将自动转换为1,false自动转换为0。
- if的条件中,
- 可判断为true的有:true、非零数字、非空字符串、非空对象({ }不是空对象,[ ]是空对象);
- 可判断为false的有:false、数字0、空字符串、空对象(null)、未定义(undefined)。
- 注意:任意非零数判断为true,但true并不能判断为任意非零数。实际上,仅有(true==1)与(false==0)为真。
- 作为对象初始化,无new也无参数时,Boolean为false值;有new但无参数,为true。
- 一个trick: [ ] == ![ ] = true
5. Math
(面试的时候让我写有什么方法,真的一脸懵逼,从来不用,于是一个都没写出来)
- 主要方法
- Math.abs(x)
- Math.cos(x)
- Math.acos(x)
- Math.sin(x)
- Math.asin(x)
- Math.tan(x)
- Math.atan(x)/Math.atan2(x)
- Math.ceil(x):向上取整
- Math.floor(x):向下取整
- Math.round(x):四舍五入
- Math.exp(x)
- Math.log(x)
- Math.max(x,y)
- Math.min(x,y)
- Math.pow(x,y)
- Math.sqrt(x)
- 属性
- Math.PI
- Math.E
- Math.LN2
- Math.LN10
- Math.LOG2E
- Math.LOG10E
- Math.SQRT2
- Math.SQRT1_2
- 特性
- Math不是对象类,没有构造函数、无需创建对象
6. Date
- 主要方法
- Date():当前日期时间
- getFullYear():获取年份
- getMonth():获取月份(0~11)
- getDate():获取日
- getDay():获取周几(0~6)
- getHours():获取小时
- getMinutes():获取分钟
- getSeconds():获取秒
- getMilliseconds():获取毫秒
- getTime():返回1970.1.1至今毫秒数
- parse():返回1970.1.1至指定时间毫秒数
- setFullYear(y,m,d)
- setMonth(m,d)
- setDate(d)
- setHours(h,m,s,ms)
- setMinutes(m,s,ms)
- setSeconds(s,ms)
- setMilliseconds(ms)
- setTime(ms)
- toString()
- toDateString():日期部分转字符串
- toTimeString():时间部分转字符串
- 属性
- 同Boolean
网友评论