闭包
闭包应用场景:防抖,节流,库的封装,保证数据的私有性,可避免变量被污染
可以避免变量被污染
私有化
(function(){
let a =2;
let b = 3;
function a(){
}
return{
a
}
})
外部可以访问到但是不能修改里面的内容,和外面的不会冲突
保存变量,常驻内存,延长变量的声明周期
let a = "xx"
在script里面
function fn(){
let b = 1
}
而b在local里面
AO是一个临时变量对象,在程序执行完后,会被垃圾回收机制回收,
直接调用闭包里面的changeBy()方法是不能访问会报错,访问c1的privateCounter也是undefined,保证了数据的私有性
要调用return里面的方法才对,
控制台返回2
new关键字
new完之后,这个函数才是构造函数
person1.fn()
控制台输出…
下面的创建空对象有何区别
-
创建一个空对象,let obj = Object.Create(null)
没有原型链 _ proto _
-
let obj2 = {}
有原型链
只是用来保存某些值,不去调用原型链的方法,用第一种方法, 效率高,
new的一瞬间做了什么事情
1创建一个空对象
let obj = new Object();//称之为基类
或是let obj = {}
2设置原型链
obj. _ proto _ = Person.prototype
指向构造函数的原型
3改变this的指向
let result = Person.call(obj)
让结果指向object
4判断返回值类型
if(typeof (result)==“object”){
person1 = result//如果是引用类型,就返回引用类型的对象,默认情况下函数返回undefined,但是在构造函数里面默认返回新创建的对象
}else{
person1 = obj
}
事件委托
事件发身在谁的身上,就给谁添加委托,
nodeName
原始值和引用值类型及区别
原始值是存储在栈中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。
包含简单数据类型:undefined、null、symbol、boolean、number 和 string ;可以通过typeof 运算符来判断一个值是否在某种类型的范围内,如果它是原始类型,还可以判断它表示哪种原始类型。
引用值存储在堆中的对象,放在变量的栈空间中的值是该对象存储在堆中的地址,也就是说,存储在变量处的值是一个指针(内存地址),指向存储对象的堆内存中。
包含:Object、function、array等。
区别:简单数据类型的值是储存在栈中,当把一个变量传递给另一个变量时,是把一个栈中的东西复制到另一个到栈中,并且这两个变量互不影响,修改其中的变量值时,不会改变另外一个变量的结果。
复杂数据类型是把引用变量的名称(内存地址)存储在栈中,但是把其实际对象存储在堆中,栈中的内存地址指向堆中的实际对象,当把引用对象传递给另一个变量时,复制的其实是指向实际对象的指针(内存地址),此时两者指向的是同一个数据,若通过方法改变其中一个变量的值,则访问另一个变量时,其值也会跟着改变, 因为JavaScript 中对象的赋值是默认引用赋值的。
js延迟加载方式
- defer和async
- 动态创建DOM,创建script,插入DOM中,加载完后callback
- 异步载入js
跨域问题解决
jsonp
document.domain+iframe
window.name、window.postMessage
服务器设置代理页面
双飞翼布局和圣杯布局
typeof的使用
typeof Symbol()
//Symbol
typeof ''
//String
typeof true
//boolean
typeof 1
//number
typeof new Function()
//function
typeof undefined
//undefined
typeof null
//object失效
typeof []
//object失效
typeof new Date()
//object无效
typeof new RegExp()
//object无效
Object.prototype.toString.call()
在JS中,可以通过Object.prototype.toString
方法,判断某个对象之属于哪种内置类型。
Object.prototype.toString.call(null)//[object Null]
Object.prototype.toString.call(undefined); //[object Undefined]
Object.prototype.toString.call(“abc”);//[object String]
Object.prototype.toString.call(123);//[object Number]
Object.prototype.toString.call(true);//[object Boolean]
Function fn(){
console.log(“test”);
}
Object.prototype.toString.call(fn);//[object Function]
var date = new Date();
Object.prototype.toString.call(date); //[object Date]
var arr = [1,2,3];
Object.prototype.toString.call(arr); //[object Array]
var reg = /[hbc]at/gi;
Object.prototype.toString.call(reg); //[object RegExp]
function Person(name, age) {
this.name = name;
this.age = age;
}
var person = new Person("Rose", 18);
Object.prototype.toString.call(person); //[object Object]
而Object.prototype.toString.call()不能准确判断person是Person的实例,要用instanceof来进行判断,
console.log(person instanceof Person); // true
constructor 的缺点
无法检测null和undefined,不稳定,
var aa=[1,2];
console.log(aa.constructor===Array);//true
console.log(aa.constructor===RegExp);//false
console.log((1).constructor===Number);//true
浏览器的本地存储
sessionStorage和localStorage
sessionStorage用于存储会话中的数据,这些数据只是用在同一个会话的页面才能,当会话结束数据随之销毁,sessionStorage不是一种持久化的本地存储, 仅仅是会话级别的存储
localStorage用于持久化的本地存储,除非主动删除数据
Cookie
cookie是以小的文本文件形式完全存储在客户端,服务器知道正在和哪个客户端通信,以及保持与已识别出的客户端通信。cookie的最大为4k,
会话cookie记录用户访问站点的设置和偏好,退出浏览器会话cookie会被删除
持久cookie存储在硬盘,维护某个用户周期性访问的站点的配置文件或登录名
原理:首次访问web站点,服务器通过set-cookie首部将cookie(包含多个键值对)存放到cookie数据库中,后面用户再次访问同一站点,浏览器会将键值对来查找服务器为其访问积累的信息
每次访问网站,浏览器通常每次只向网站发送2-3个cookie,所有cookie进行传输会降低性能,而且会引发隐私问题
一般cookie缓存图片
Cookie
数量和长度的限制,有些状态不可能保存在客户端
数组和类数组
数组和类数组都可用下标访问每个元素,都有length属性。
数组对象的类型是Array,
类数组对象的类型是object,
数组遍历可以用 for in和for循环,
类数组只能用for循环遍历。
数组转换为类数组
var arr = [1, 2, 3, 4];
var obj = { };
[].push.apply(obj, arr);
console.log(obj);
//输出为原型为Object 的一个对象
类数组转换为数组
方法一
Array.prototype.slice.call(arrayLike,start);
方法二 Array.from(arrayLike)
方法三 扩展运算符(…)
JS七大原始数据基本类型
Boolean,null,undefined,number,string,symbol,bigint
引用数据类型
对象Object,普通对象object,数组对象array,正则对象regexp,日期对象date,数学函数math,函数对象function
null不是对象
虽然 typeof null 会输出 object,为了性能考虑使用低位存储变量的类型信息,000 开头代表是对象然而 null 表示为全零,所以将它错误的判断为 object 。
‘1’.toString()为什么可以调用
在这个语句运行的过程中做了下面几件事情
var s = new Object(‘1’)
s.toString()
s=null
而1.toString()会报错
小数点会被认为带有小数的数字整体,应该加一个空格或是加括号
内存泄漏
任何对象在不需要之后仍然存在
垃圾回收机制,计算引用每个对象的其他对象的数量,引用数量为0或是只引用了循环,该对象的内存会被回收
setTimeout的第一个参数是字符串,闭包,控制台日志,循环,都会造成内存泄漏
JavaScript提供了数据类型和访问器属性两类
数据类型
value属性的值
writable 决定属性能否被赋值
enumerable决定for in能否枚举该属性
configurable决定该属性能否被删除或者改变特征值
访问器属性
getter,函数或undefined,取属性值时被调用
setter,函数或undefined,设置属性值时被调用
装箱转换
a+b
先检测对象是否存在valueOf方法,若有返回原始类型,使用该值进行强制类型转换;valueOf没有返回原始类型,就用toString方法的返回值,,如果valueOf和toString都不返回,触发TypeError错误
在执行1+'2’的过程中,执行了装箱转换,
Number(1).toString()+‘2’
如果没有如果其中一项是字符串,v8默认将另外一个值转换为字符串
[]+[]会被隐式调用toString()方法,一个[]
转换为原始值’’
{}+{}会被隐式调用toString()方法,一个{}
转换为原始值"[object object]"
[]==0返回true,![]==0返回true,!![]返回true
[]==![]返回true
[]转换为数字为0,[]转换为布尔值true,![]则为false,转换为数字为0,0 == 0,结果为true
BigInt
在数字末尾追加n即可
也可以创建BigInt()构造函数
BigInt(“9007199254740995”); // → 9007199254740995n
BigInt不支持一元加号运算符
不允许在bigint和 Number 之间进行混合操作
不能将BigInt传递给Web api和内置的 JS 函数
Number
toString()返回数值对象的字符串
valueOf()返回原始数值
toFixed(n)返回包含指定小数位数的字符串
toExponential(n)返回科学计数法的字符串
toPrecision()返回数值最恰当形式
Number.isFinite()检查数值是否有限,不是数值返回false
Number.isNaN()检查是否为NaN,不是NaN返回false
Number.parseInt()和Number.parseFloat()
Number.isInteger()判断是否为整数,不是数值返回false
Math对象的常用方法
略
undefined转为数值为NaN,null转为数值为0
字符串
‘abc’+{
value:10,
toString: function(){
return this.value.toString();
}
}
结果为’abc10’
String()
indexOf(),返回指定某个字符串值在字符串首次出现的位置,区分大小写
数组
创建数组方法:
- 数组字面量
- let count = [1,2,3]
- 构造函数Array()
- let a1 = new Array()
数组长度length可以用Object.defineProperty()来改成只读
arr.push(n),原数组末尾增加指定元素
arr.unshift(n),原数组开头增加指定元素
arr.delete(n),删除原数组下标为n的元素
arr.pop(n),删除原数组末尾元素
arr.shift(n),删除原数组开头元素
arr.splice(a,b,c),在下标为a的位置,删除b个元素,添加元素c,
-
a可以为负值,b可以为0即不删除,c可以为多个元素
-
b和c为0,从a开始删除后面所有元素
arr.join(),将数组转换为字符串,默认逗号分割,arr.join("-"),按-分割
arr.reverse(),颠倒数组元素的顺序
arr.sort(),排序数组元素,按照字母表顺序排
arr.concat(m,n),返回
一个新的数组,m和n可以是元素也可以是数组
arr.slice(a,b),返回
指定数组下标为a到b-1的元素,如果b大于数组长度或是b省略,会提取到原数组的末尾
arr.includes(a),判断数组是否包含指定的值,有则返回true
arr.filter(function(a)),传进一个参数a,根据方法,返回一个新的数组,
arr.indexOf(),返回指定某个值在数组首次出现的位置,区分大小写
构造函数方法
Array.from(),将可遍历的对象或是类似数组的对象转为真正数组
Array.of(),将数值转换为数组
数组去重:
return […new Set(arr)]
数组去重[https://segmentfault.com/a/1190000016418021]
四种遍历语法
for循环
forEach
- 回调参数分别为value,index,array,缺点在于无法中途跳出
for…in
- 用于遍历可枚举属性,功能类似于Object.keys(),遍历不到constructor和length属性,主要用于遍历对象而设计,不适用与遍历数组
for…of
- ES6新增,提供了所有数据结构的统一操作接口
- entries()返回一个遍历器对象,用于遍历[键名,键值]组成的数组,对于Set,键名和键值相同,对于Map,Iterator接口,默认entries方法
- keys()返回遍历器对象,遍历所有键名
- values()返回遍历器对象,遍历所有键值
不是所有类似数组的对象都有Iterator接口,用Array.from()方法将其转换为数组
普通的对象必须要部署接口后才能使用,用for…in可以,用for…of必须加上Object.keys(obj)方法。
let a = {a:1,b:2,c:“3”}
for(let key of Object.keys(a)){
console.log(e,a[key])
}
json字符串转json对象
JSON.parse()
json对象转为json字符串
JSON.stringify()
obj.toJSONString()
json字符数组转为json数组
JSON.parse()
ajax的过程
创建XMLHttpRequest对象/异步调用对象
创建新的HTTP请求,指定方法URL和验证信息
设置响应HTTP请求状态变化的函数
发送HTTP请求
获取异步调用返回的数据
使用js和DOM实现局部刷新
异步加载
动态插入script标签
通过ajax获取js代码通过eval执行
script标签添加defer后async属性
创建并插入iframe,异步执行js
正则表达式
范围类[a-z0-9-]表示a到z和0-9和-的之间的任意字符
元字符1,匹配不属于abc的字符
-
. (点),除了回车符和换行符的所有字符
-
\d,[0-9]数字字符
-
\D,[ ^0-9],非数字字符
-
\s,[\t\n\x0b\f\r],空白符,\f换页符,\r回车符,\t水平制表符,\n换行符,\x0b垂直制表符
-
\S,[ ^\t\n\x0b\f\r],非空白符
-
\w, [a-zA-Z_0-9],单词字符,字母数字下划线
-
\W,[ ^a-zA-Z_0-9],非单词字符
-
^ 以xxx开始,$ 以xxx结束,\b,单词边界,\B,非单词边界
-
{n},出现 n 次
-
{n, m},出现 n 到 m 次
-
{n,},出现 n 次或更多次
贪婪模式——尽可能多的匹配
非贪婪模式——尽可能少的匹配
分组
或
反向引用
变量提升/预处理
console.log(username)//undefined
var username=‘11’
而函数可以
//执行上下文/EC
eval是什么?
把对应的字符串解析成js代码并运行
避免使用eval,不安全,耗能
原型链,原型对象
原型链是用来继承和共享属性的对象组成的对象链
原型对象是对象自带的隐式的_ proto _属性,如果原型对象的原型不是null,就是原型链
js阻止冒泡
ev.stopPropagation()
Ajax
优化浏览器和服务器之间的传输,减少不必要的数据往返,减少带宽,可以通过异步模式,提升用户体验
ajax对搜索引擎支持比较弱,安全问题,不容易调试
如何解决跨域问题?
jsonp
回调执行函数,handleCallback()
跨域资源共享,CORS,
获取UA
function whatBrowser() {
document.Browser.Name.value=navigator.appName;
document.Browser.Version.value=navigator.appVersion;
document.Browser.Code.value=navigator.appCodeName;
document.Browser.Agent.value=navigator.userAgent;
}
eventloop
- macro-task(宏任务)
- setTimeout
- setInterval
- set Immediate
- micro-task(微任务)
- Promise
- process.nextTick
改变this指向
-
apply
function bindThis(f, oTarget) { return function() { return f.apply(oTarget, arguments) } }
-
bind
function bindThis(f, oTarget) { return f.bind(oTarget) }
-
call
function bindThis(f, oTarget) { return function() { return f.call(oTarget, ...arguments) } }
lue=navigator.appVersion;
document.Browser.Code.value=navigator.appCodeName;
document.Browser.Agent.value=navigator.userAgent;
}
#### eventloop
- macro-task(宏任务)
- setTimeout
- setInterval
- set Immediate
- micro-task(微任务)
- Promise
- process.nextTick
#### 改变this指向
1. apply
```js
function bindThis(f, oTarget) {
return function() {
return f.apply(oTarget, arguments)
}
}
-
bind
function bindThis(f, oTarget) { return f.bind(oTarget) }
-
call
function bindThis(f, oTarget) { return function() { return f.call(oTarget, ...arguments) } }
^abc ↩︎