JS篇
js中的装箱和拆箱操作
装箱:把基本数据转换成对应的引用类型操作; 拆箱:把引用类型转换成基本类型。
装箱步骤:
- 运算符 . 提供装箱操作,根据基础类型构造一个临时对象,这样能够让我们在基础类型上调用对应对象方法。
装箱机制会频繁的产生临时对象,在一些性能要求比较高的场景下,我们应该尽量避免对基本类型做装箱转换。
拆箱
toString() //返回文本值
valueOf() //返回原始值
- 这两个方式一般由js隐式的去调用,在数值运算中,会优先valueOf(),在字符运算中优先调用toString()
js的冒泡和捕获事件,以及在不同浏览器怎么阻止冒泡、捕获事件以及默认事件
答案解析:
DOM2级事件规定的事件流包括:事件捕获、目标阶段、事件冒泡
事件冒泡: 从实际操作的元素(事件)向上级元素一级一级执行下去,直到到达根元素
事件捕获: 浏览器检测元素的最外层祖先<html>一级一级向下执行事件,直到到底目标元素
事件委托: 利用的是事件冒泡机制实现的,通俗来说就是将元素的事件委托给它的父级或者是更外级元素处理
适合采用事件委托机制的事件有:click
、mousedown
、keyup
等,而 mouseover
和 mouseout
不适合
事件委托优点:
- 动态新增的子元素无需重新绑定事件
- 只需要将同类元素的事件委托给父级或者更外级的元素,不需要给所有同类的元素都绑定事件,这样可以减少内存空间占用,提示性能
js的冒泡和捕获事件都是描述事件触发的时序问题,冒泡指的是由子节点向父节点的顺序触发事件,捕获则是由父节点向子节点的顺序触发事件;默认事件是当我们在页面执行一些动作时,浏览器触发的默认事件,比如点击a标签跳转页面的时候,自动触发click事件、鼠标右击的时候 执行的oncontextmenu 事件、以及鼠标滚动的时候、表单的提交行为等等。
冒泡、捕获事件的阻止
- w3c中使用
e.stopPropagation()
IE使用e.cancelBubble = true
默认行为的阻止
- w3c使用
e.preventDefault()
阻止默认行为,IE使用e.returnValue = false
或者是return false
来阻止
对作用域的理解,let和var的区别
答案解析:
作用域是分有函数作用域、块级作用域,可以理解为变量可使用的范围、区域。
let和var的区别在于:
- let是块级作用域,不存在变量提升(存在暂存性死区)、不能重复声明、声明变量不可作为window属性
- var是函数作用域、存在变量提升、能重复声明、声明变量可以作为window属性
对闭包的理解
答案解析:
官方解释指一个拥有很多变量和绑定了这些变量的环境的表达式为闭包。通俗理解为是指有权访问另一个函数作用域中的变量函数。
js允许使用内部函数--即函数定义和函数表达式位于另一个函数的函数体内,而且这些内部函数可以访问它们所在的外部函数中所声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包
闭包特性
- 封闭性:如果不是闭包函数自动暴露内部的私有变量的情况下,外部变量是无法直接访问到闭包内部的函数
- 持久性:因为js的垃圾回收机制所以在函数使用完后,js会自动销毁函数,但是闭包函数不会立即被销毁
可使用场景
- 设置私有变量的特权访问方法
- 应用写防抖和节流函数
闭包的产生来自于js的变量作用域。在js中,变量的作用域属于函数作用域,当函数执行完全之后,作用域就会被清理,内存也会随之被回收。而封包因为是父函数内部的子函数,可以访问到父函数变量,以至于父函数执行完成,但是作用域也不会销毁,而一直保存在内存中直至闭包函数被销毁。而利用这个特性就可以将定时器保存在内存中,但我们执行用户操作的时候,判断定时器的执行情况决定是否执行接下来的操作
- 因为闭包的可以直接访问到函数的变量,且执行完不会立即被销毁,所以函数的局部变量可以当成全局范围的函数使用
- 采用函数引用方式的setTimeout的调用,可通过闭包形式方法传入的参数
function calllater(A,B,C){
return (function(){
A[B] = C
})
}
var p = new callater('style','diplay','none');
setTimeout(p,200);//此时会执行p指向函数的内部函数
对原型链、原型对象的认识
答案解析:
原型: 每个js对象在创建时,会自动关联到另一个对象,这个对象就是我们所说的原型,而每一个对象都会从这个原型中去继承属性 。 每一个函数都有prototype属性,这个属性指向函数的原型对象。
原型链:每个对象都有一个属性(除null外),即为原型链,这个属性指向该对象创建的构造函数的原型属性。
constructor:每个原型都有一个constructor属性,这个属性指向该原型关联的构造函数
Person === Person.prototype.construtor
Function、Object原型链之间的关系
- Function 是一个函数(函数是Function的实例对象)
Function.__proto__ === Function.prototype
- Object 是一个函数(函数是Function的实例对象)
Object.__proto__ === Function.prototype
- Object是原型链的顶层
Object.prototype === null
- Function.prototype是普通对象
Function.prototype.__proto__ === Object.prototype
js的继承有那些方式、分别有什么优缺点
答案解析:
- 原型链继承
function A(name){
this.name = name
}
A.prototype.age = 10;
function B(){
this.sex = 'ss'
}
B.prototype = new A() // B的原型对象指向A的实例,那么B的实例对象的原型链就会指向A的实例
var b = new B();
console.log(b.age) // 10
特点:1、可继承属性:实例构造函数属性、父类构造函数、父类原型属性
缺点:1、共享父类实例属性(共享原型属性)2、 新实例无法向父类构造函数传参
- 借用构造函数继承
function B(){
A.call(this,'qiqiq') // 将this对象指向A对象
this.sex = 'ss'
}
var b = new B();
console.log(b.age) // 10
特点:1、可继承属性:父级构造函数属性 2、可向父实例传参
缺点:1、无法实现父级构造函数复用 2、每个实例都有父类构造函数复本 3、只能继承构造函数的属性
- 组合继承
function B(){
A.call(this,'qiqiq') // 将this对象指向A对象
this.sex = 'ss'
}
B.prototype = new A()
//修复构造函数的指向,因为有需要指向两个构造函数
B.prototype.constrcutor = B
var b = new B();
console.log(b.age) // 10
特点:1、结合两者优点:传参、复用 2、可继承属性:父级构造属性、父级原型属性、实例构造函数属性
缺点:1、需要调用两次父类构造函数
- 寄生式继承
function box(obj){
function F(){}
F.prototype = obj;
return new F(){}
}
var a = new A();
var b = box(a); //返回父级的实例,每次都是新的,可以自定义去添加属性和方法
- 寄生式组合继承
(function(){
//创建一个无属性的函数,将它原型指向父级原型
var super = function(){};
super.prototype = A.prototype;
//将其实例作为子类原型对象
B.prototype = new super();
})()
function B(){
A.call(this,'qiqiq') // 将this对象指向A对象
this.sex = 'ss'
}
B.prototype.constrcutor = B
特点:1、通过寄生方式,砍掉父类实例属性,不必在调用两次父类构造函数
语术表达
- 原型链继承
将子类的原型对象指向父类的实例对象,可以实现继承父类的属性、构造函数属性、父类原型对象属性,但是所有子类实例回公用这些属性,一旦其中一个子类实例改变父类属性,则会影响到其他子类继承的信息。
- 构造函数继承
在子类的构造函数调用call函数,将子类的构造函数的内置对象this指向父类,则在子类通过new实例化对象的时候会将父类构造函数
- 组合继承
- 寄生式组合继承
js的箭头函数和普通函数的区别
答案解析:
- 不能改变函数this对象的指向
- this的指向的是箭头函数在定义时的父级上下文
- 不可以使用new操作
- 不能使用arguements对象(可以使用rest参数代替)
- 不是使用yield命令,不能作为Generator函数
- 箭头函数没有prototype原型对象。
执行new操作发生了什么
答案解析:
var a = new A()
- 创建一个Object实例
var a = new Object()
- 将实例的原型链执行类的原型对象
a[[Prototype]] = A.prototype 等价于 a.__proto__ = A.prototype
- 调用call函数改
this
指向,执行对应的构造函数
promise对象的理解以及asyns、await的理解
答案解析:
promise是异步回调的一种解决方法,可以理解为一个容器,里面保存着异步操作在不同状态下可能执行的事件。异步操作的待执行、执行成功、执行失败分别对应着promise对象的pending、fullfilled、rejected.只有异步操作的结果能决定这些状态,且这些状态均为不可逆。
asyns、await着两个关键词一定要和promise对象配套使用才能体现价值所在,asyns这个关键词可以将普通函数转换成异步函数,await则为异步函数的提供串行执行的方案,await跟随的promise对象的状态变化之后才能执行下一步操作。
- promise.all的使用
promise.all可以将多个promise实例包装成新的promise实例
- 接收一个对象数组作为参数,可以是其他值,只有是promise会等待其状态变化
- 当所有的子promise的状态完成,则返回值是全部值的数组
- 如果有任意一个失败,则promise失败,返回值是第一个失败的子promise的结果
- promise.race的使用
- 任意一个返回结果后,无论结果是成功还是失败,但是进程不会立即停止
ES迭代的特性
答案解析:
- let和const关键词
- 解构赋值
- 使用...展开运算符
- 添加class、super、extends关键词
- 箭头函数
- 增加Set(集合)、Map(字典)数据类型,可用于去重和存储,Set可用于数据去重、map可以用键值对形式存储数据,查询速度极快
- generators生成器
是一个能返回一个迭代器的函数,实现惰性加载数据。在普通函数多加
*
,在函数体可以使用yield
关键词,让我们的代码进行等待,也可以运用在异步编程中,解决异步陷阱。让异步操作可控
- promise对象
- async/await关键字
使用ES6遍历数组的方法、以及不同方法的区别
答案解析:
- for(var i = 0 ; i < arr.length; i++) 无限制,break、continue均可选
- arr.forEach(function(val){ }) , 不可以使用break,也不能使用return 函数
-
for(var index in arr)
效率较低,并且index是字符,不是数字,这个需要注意到,同时会遍历原型链上的可枚举的属性,可以结合obj.hasOwnProperty()
来过滤掉 - for(var item of arr) item是arr每次遍历所对应的value(目前最优方案,也支持字符串的遍历)
- some() 用于检测数组中是否存在一些满足条件元素, 返回值为true 或 false ,如果有一个满足条件的则函数返回true,否则返回false
arr.some((item,index,arr)=>{return item % 2==0 })
- every() 和some相反,如果数组中全部元素满足条件,则返回true,有一个不满足条件则返回false
- filter()是用来过滤筛选出符合条件的元素,返回内容为新的数组
arr.filter((item)=>{
return item%2 == 0
})
- map是一个数组的映射函数,对数组中的每个元素按照映射返回新的数组
arr.map(item=>{
return item*2
})
- reduce函数累加器,可以为数组中的每一个元素依次执行回调函数(不包括未被赋值或者被删除的元素)
arr.reduce(callback, [initValue]);
//其中callback包含四个参数
1. previousValue (上一次回调返回值或者初始值)
2. currentValue (数组中当前被处理的值)
3. index (当前元素在数组中索引)
4. arr(调用的数组)
// iniValue 表示初始值
事件循环机制
答案解析:
事件循环机制是用来解决js单线程执行机制,而导致一些简单执行操作会因为等待一些耗时间的请求、涉及I/O执行事件 而无法延迟执行的情况。从广义角度上讲,事件循环机制将任务分为同步任务和异步任务
其执行的机制是如下:
- 所以同步任务都在主线程中执行,形成一个任务栈
- 除了主线程之外,还存在一个任务队列,一旦异步任务执行完成,就在任务队列压入一个事件
- 等待任务栈中的所有任务执行完成,从任务队列中取出事件的回调函数放入任务栈中执行
- 循环以此,直至任务完成
# 任务执行的优先级
同步任务 > promise.nextTick() > promise > setTimeout(fn) > setInterval(fn) > setImmediate(fn) > setTimeout(fn,time) > setInterval(fn,time) > setImmediate(fn,time)
js事件循环机制的执行顺序如下:
- 执行完全部的同步任务,以及promise的构造函数
- 将所有promise的构造函数后的第一个then函数压入异步队列
- 再将所有的promise的第二个then函数压力异步队列,依次压入全部的then函数
- 执行异步队列中的then()函数
- 最后执行setTimeout()这些延迟函数
js的深浅拷贝
答案解析:
js的深、浅拷贝主要是针对于引用类型而言,浅拷贝就是复制了对象的引用,拷贝对象发生变化,原对象也会变化。深拷贝是申请新的空间 复制了对象的属性,拷贝对象与原对象之间不存在关联。
浅拷贝
- Object.assign()、利用
=
赋值操作符 、{...obj} 展开运算符
深拷贝
- JSON.stringify、JSON.parse 转换拷贝,但是不足时如果对象值存在undefined、null、正则表达式、函数时,则无法拷贝,会置空。
- 递归的方式判断对象的每个元素类型,依次深挖,逐一进行拷贝
function deep(obj){
if(!obj) return obj;
var objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj == 'object'){ // obj为null或者是 object或者array都是返回 object
for(var key in obj){
if(obj.hasOwnPrpety(key)){ //该函数会返回一个布尔值,指示对象自身属性中是否具有的该指定的属性
objClone[key] = deep(obj[key]); // 采用递归深层遍历
}else{
objClone[key] = obj[key]; //基本数据类型直接拷贝即可
}
}
}
return objClone;
}
要知道js的数据类型有那些方法,这些方法有什么差异
答案解析:
js的基本数据类型:String、Number、Boolean、undefined、Symbol、NaN、null,引用类型有:Object、Aarray.
null和undefined的区别
- null:Null类型,可以认为对象类型,代表是一个空对象指针。
- undefined:Undefined类型
区别:
- 基本类型存储在栈中(栈内存是由程序自动向操作系统请求分配的内存,其回收速度快、使用方便);赋值传递
- 引用类型存储在堆中(堆内存是由开发者向操作系统申请的,分配速度慢、不连续);引用传递
判断数据类型
-
typeof
可以用来判断基本数据类型。使用方式是 typeof + 变量,返回的内容是变量的数据类型
typeof [] //object
typeof function(){} //'function'
-
instanceof
用来判断某个对象是否属于另个对象的实例。使用方式是A instanof B,返回内容为true或者false.
但是只能判断的是复杂的数据类型,对于基本数据类型如果是通过字面量的方式创建是基本数据类型,而通过实例方式创建的是对象数据类型。instanceof判断原理是通过寻找实例的原型链中是否存在类型的原型。实现方式如下:
var _instanceof = function (left,right){
let prototype = right.
}
-
constructor
从原型链的角度,构造函数就是新对象的类型,而construtor属性是新建对象的构造函数中原型对象的属性,指向构造函数。
''.constructor == String
-
Object.prototype.toString()
利用对象的原型方法,再通过call、apply调用返回正确类型信息
Object.prototype.toString().call(window) //'[object global]'
Object.prototype.toString().call(document) //'[object HTMLDocument]'
js的垃圾回收机制和内存管理
答案解析:
内存泄漏 :不再用到的内存,没有及时释放,就是内存泄漏。
造成影响: 对于持续运行的服务进程,必须及时释放不再用到的内存,否则内存占用越来越高,轻则影响系统性能,重则导致进程崩溃。
js的垃圾回收机制:是指js的变量或者函数在使用完成以后自动回收内存的机制。垃圾是指没有引用的对象或者是几个对象之间相互引用但是根部访问不到的对象。 常用的方式有两种:
标记清除
垃圾收集器会把在内存中存储的变量加上标记,当执行流离开该环境,会去除环境中的变量以及被环境所引用的变量的标记。之后会给环境变量无法访问到的内存变量再次加上标记,加上标记的也就是需要去除的变量。最后,垃圾收集器完成内存清除功能,销毁那些带标记的值并且回收内存。
引用计数
跟踪记录每个值被引用的次数。当声明一个变量并且将一个引用变量赋给该值时,该值的引用次数加1,相反如果一个已经引用了该值的变量被赋给其他值,则该值的引用次数减1,如果引用次数为0,则垃圾收集器下次再运行时会释放引用次数为0的内存。
存在相互引用的情况,导致双方引用次数为2,则会陷入循环无法释放内存的情况
js的字符串/数组 常用函数
答案解析:
字符串(原来这些函数都不会改变字符串本身,返回的都是新的字符串内容)
- indexOf()/lastIndexOf 寻找某个字符在字符串的 第一个/最后一个 下标位置
- slice(x,y) 截断函数内容是[x,y) ,y可以为负数 y + s.length
- substring() 截断函数内容是[x,y) ,y 可以为负数 y + s.length,与上不同的是,当x>y 自动互换位置
- substr(x,len),截断内容是[x,x+len] ,其第二个参数是截断的个数
- split() 字符转数组函数
var s ='asfg'
s.split() //['asfg']
s.split('') //['a','s','f','g']
- s.charAt(index) 根据下标数返回对应的value值
- s.replace(x,y) 找到第一个x子字符串
数组
- contract() 连接数组 ,返回连接后的新数组
a = [(1,2,3),4]
a.contract([5,6]) // 3,4,5,6 因为逗号字符串的原因 则之后取最后一个元素
- join()数组转字符
var a = ['a','s','v']
a.join() // a,s,v
a.join('') //asv
a.join('-') // a-s-v
- splice(index,howmany,element) 截取、删除、插入函数(根据参数来定义) 改变原数组
var a = [1,2,3,4,5]
s.splice(1) // 删除index后的所以元素
s.splice(2,3) // 删除 index后3个元素
s.splice(1,0,5) //homemany为0时 则可插入元素 ,不为0时则替换内容
js遍历对象的方法
- for..in 最常规的遍历方式,但是会得到在原型链上的属性 ,使用obh.hasOwnProperty(key)筛选
- Object.keys(obj) 返回的是对象中所有可以枚举的属性的数组,不会走原型链, 通过foreach()遍历
var obj ={"a":1,"b":3};
Object.keys(obj).foreach((key)=>{
console.log(obj[key])
})
- Object.getOwnPropertyNames() 返回自身对象的属性名所组成的数组,包括不可枚举对象
- Reflect.ownKeys() 返回自身对象属性名以及原型链上的所有属性名所组成的数组
delete的使用场景
答案解析:
使用delete删除无效的情况
- 使用let、var、const声明的变量或者是函数声明删除均无效
- 删除数组时,元素会被删除、但是length值不变化
- Map、Object、Array的内置变量不可删除
- 原型对象的属性不可删除
this对象的指向
答案解析:
this对象表示是一个函数对象在运行的过程中,内部生成的一个内置函数,只能在函数内部使用。记住一点是this是和函数执行的环境有关,与声明环境无关(仅代表在普通函数,箭头函数并非如此)
- 方法调用模式
//案例:
var obj = {
name:'ssss',
sayName:function(){
console.log(this.name) //ssss
}
}
解析:当函数作为对象的一个属性,则可成为该函数的方法,当该函数被调用时,方法的this的对象被绑定在该对象中。
- 函数调用模式
//案例
var name ='ddd'
function obj(){
console.log(this.name) //dddd
}
obj()
解析:当函数并非一个对象属性,而是正常的函数被调用的情况下则有,该this对象被绑定在window对象上
- 构造函数模式
function obj(){
this.name= 'dddd'
}
var s = new obj();
console.log(s.name)
解析: 在一个函数前面加上new时,此时会创建一个绑定到该函数的prototype的对象,并且该函数会作为该对象的构造函数,this此时指向该对象
- apply/bind/call调用模式
解析:主要是改变this所绑定的对象
Map和object的区别
map对象保存键值对,任何值都可以作为一个键或者一个值,用for...of循环为每次迭代返回一个[key,value]的数组
区别:
- 每一个对象通常都有自己的原型,每一个对象都有prototype的属性
- 一个对象的键只能是字符串或者是Sysmbols,但是map的键可以是任意值
- map的键值对个数可以通过size属性获取,而对象的元素个数可能只能通过遍历手动确认
字符串是基本数据类型为什么可以调用数组的方法
js的装箱机制,当我们访问str时,访问过程从内存中读取这个字符串的值时,后台会执行以下处理:
- 创建String这个实例,生成一个基本包装类型对象
- 在实例中调用指定的方法
- 销毁实例
为什么0.2+0.1不等于0.3呢?
原因在于在js采用IEEE 754的双精度标准,计算机内部存储数据的编码的时候,0.1在计算机内部根本不是精确0.1,而是有舍入误差的,在代码编译过程中已经被四舍五入成一个与之很接近的计算机内部数字,这样误差也就产生了。
$(document).ready()和window.onload()有什么区别?
dom文档的加载步骤
- 解析HTML结构
- 加载外部脚本和样式表文件
- 解析并执行脚本
- dom树构建完成(DOMContentLoaded)
- 加载图片等外部文件
- 页面加载完毕
-
window.onload
方法是在网页中所有元素(包括元素所有关联文件)完全加载到浏览器后才执行的。 -
$(document).ready()
方法可以在dom载入j就绪时对其进行操纵、并调用执行绑定的函数。
js/jQuery的常见的dom操作
dom的节点分为三大类:元素节点、属性节点、文本节点,其中文本节点和属性节点属于元素节点的子节点,操作时需要先取到元素节点。
获取元素节点的常用方法:
getElementId() //返回带有指定ID元素
getElementsClassName() //返回带有指定类 的数组
getElementsTagName() // 返回带有指定标签的数组
createAttribute() //创建属性节点
createElement() //创建元素节点
createTextNode() //创建文本节点
查看、设置属性节点
- getAttribute(属性名) //查看属性节点
- setAttribute('属性名','属性值') //设置属性节点
div.style.backgroundColor = 'red'; //需要采用驼峰式写法
div.style = "backgorundcolor:red"
查看、设置文本节点
.innerText:取到或者设置节点里面的文字内容
.innerHTML:取到或者设置节点中的HTML代码
根据层次查看节点
.childNode() //获取元素的所有子节点
.firstChild() //获取元素的第一个子节点
.lastChild() // 获取元素的最后一个子节点
.previousSibling() // 获取当前节点的前一个兄弟节点
.nextSibling() //获取当前节点的后一个兄弟节点
克隆节点
cloneNode(true) //克隆当前节点,以及当前节点的子节点
cloneNode(false) //克隆当前节点,不包括当前节点的子节点
js的常见函数操作
- 对小数的相关操作
- 截取小数部分,取整数
parseInt()
- 向上取整,有小数则加1
Math.ceil()
- 向下取整,有小数则去掉
Math.floor()
- 小数部分四舍五入
Math.round()
- 四舍五入为指定小数位数的数字
num.toFixed()
- 截取小数部分,取整数
- js的字符串相关函数操作
- 字符串分割 返回成数组
str.split(' ')
- 字符串切割
str.substr[start,length)
- 字符串切割
str.substring[start, end)
- 字符串去前后空格:
str.trim()
- 字符串大写转小写转换:
str.toLowerCase()
- 字符串小写转小写转换:
str.toUpperCase()
- 字符串分割 返回成数组
var 和 let 、const的区别
- var 声明的变量会挂载到window ,而let和const声明的变量不会
- var 声明变量存在变量提升,let和const不存在变量提升(存在一个暂存性死区)
- let和const声明形成块作用域
- 同一作用域下,let和const不能声明同名变量,而var变量可以
- const一旦声明必须赋值,不能用null占位,基本数据类型声明后不能在修改,如果是复合类型,可以修改其属性
暂存性死区:ES6对作用域的新的语义,可以理解为程序的控制流程在新的作用域进行实例化时,在作用域中let、const声明的变量会在该作用域先创建,但是没有进行语法绑定和声明语句的赋值运算,所以是不能访问,访问会抛出错误。所以在这运行流程一进入作用域创建变量,到变量开始可以被访问的一段时间叫做TDZ(暂存性死区)
js的数据类型隐式转换情况
运行环境对隐式转换的影响
很多内置函数期望传入的值的数据类型是固定的,如:alert(value)的方法,它期望传入的是string类型,但是我们传入的是number类型或者是其他非string类型,则h会发生类型的隐式转换
操作符对数据类型转换的影响
- 当+ 作为一元操作符操作数的时候,会将数转换为数字类型
- 当+ 作为二元操作符操作数的时候,如果有一个操作数是字符则会,那么另一个操数也会转换为字符类型;如果两个都不是字符或者数字,则能转换的转换成数字,不能转换的变成NaN
- 当算数运算符除了是+号以外的其他操作数,则两个操作数都会转换成数字类型进行数字运算
数字转换的时候遵循:如果是简单数据类型,则直接转换成字符串或者数字,如果是复杂数据类型,则通过固定方法(valueOf、toString)转换成简单类型,再转换成数字或者字符串
- 转换为Boolean类型
数据类型 | 转换后的值 |
---|---|
数字0 | false |
NaN | false |
'' | false |
null/undefined | false |
注意:如果是使用new操作符创建的对象隐式转换成Boolean对象时,即使是new String('') 也是true
- 转换为number类型
数据类型 | 转换后的值 |
---|---|
非空字符串 | 如果全部为数字符合则转换成数组,如果有其他符号则转为NaN |
null | 0 |
'' | 0 |
NaN/undefined | NaN |
js的设计模式
可复用的解决方案,用于解决软件设计中遇到的常见问题
优点
- 模式都是有自己的结构和j解决方案的一系列词汇,在向其他人描述时,表达更加清晰
- 容易复用,可以通过改动一些信息去解决自己的问题
- 在代码结构上花费的时间比较少,可以有更多时间关注整体质量,且减少代码重构的风险
- 单例模式
js中最基本最有用的模式,可以用来划分命名空间,减少网页中全局变量的数量,在多人开发时避免代码的冲突。
- 工厂模式
提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。 把成员对象的创建工作转交给一个外部对象,消除对象之间耦合。
- 装饰者模式
为对象增加功能或者方法,动态给一个对象添加一些额外的职责,能够在不改变现有对象或从派生子类的前提下为其添加方法。
- 代理模式
此模式最基本的形式是对访问进行控制。代理对象和另一个对象(本体)实现是同样的接口,实际工作也是本体在做,代理对象只是负责执行所分派的任务的,不会在对象的基础上修改任何方法,也不会简化对象的接口。
- 观察者模式
定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生变化的时候,所有依赖于它的对象都得到通知并且刷新。
正则表达式
- 修饰符(修辞符的使用是并集)
- i 忽略大小写匹配
- g 全局匹配
- 元字符
- 代表次数的量词元字符
-
?
:一次或0次 -
+
:1到多次 -
*
: 0到多次
-
- 代表特殊含义的元字符
-
\d
:0-9任意一个字符 -
\D
:表示非\d -
\w
:表示数字、字母、下划线 -
\s
:空格或者空白 -
.
:除了\n
之外的任意一个字符
-
- 代表次数的量词元字符
- 常用方法
-
test
:验证字符串是否符合正则,符合则返回true,否则返回false -
exec
:捕捉符合规则的字符串 -
match
:匹配成功返回成功数组,否则返回null -
replace
:把正则匹配成功的字符串替换成新的字符串
js函数的四种调用方式
函数基本概念
- 函数的名字只是一个指向函数的指针,所以在不同执行环境、不同对象调用这个函数,函数指向的是同一个函数。
- 函数内部的两个特殊属性arguments和this,其中argument主要是用来保存函数参数,this是与函数运行环境相关联,不同运行环境指向也会不同。
函数调用方式
- 直接调用函数,this指向全局对象window
- 函数作为对象的方法调用,this指向调用的当前对象
- 通过new调用构造函数的方式,this指向当前构造函数原型
- 上下文调用模式(通过call或者apply的方式),可以实现函数模式与方法模式
Object.defineProperty
的使用
可以理解为属性拦截器,专门监控对象的属性变化。
//接收三个参数定义属性的对象、定义或修改属性的名称、定义或修改属性的值 , 返回值修改完的obj对象
Object.defineProperty(obj, prop, descriptor)
数据描述符和存取描述符可选键值
-
configurable:
为true时,该属性描述符才能够改变,也能被删除 -
enumerable:
为true时,才能够出现在对象的枚举属性,默认为false -
value:
为属性对应的值,可以是任意有效js值,默认为undefined -
writable:
为true时,该属性可以被赋值运算符改变