文章目录
1 Object添加属性:defineProperty
格式:Object.defineProperty(obj,prop,desc)
obj:需要定义属性的对象
prop:需要配置的属性名称
desc:属性描述对象
其中:desc分为两种,不可同时使用:
- 权限描述
// 权限描述对象,(不写默认值为false)
{
value:xxx,
writable:false, // 不可重新赋值,但是如果可配置,可以使用defineProperty重新赋值
enumerable:false, // 不可枚举
configurable:false // 不可删除或重新defineProperty配置,但是当writable为true时,可以再次定义来改变value值
}
// 直接索引赋值
let o = {}
o.a =1
// 相当于
Object.defineProperty(o,'a',{
value:1,
writable:true
enumerable:true
configurable:true
})
- 存取器
{
get: function(){},
set: function(){}
}
// 示例
var number = 18
var a ={name:"pp",sex:"boy"}
Object.defineProperty(a,'age',{
get(){
return number;
}
set(value){
number = value
}
})
console.log(a.age) // 18
number = 19
console.log(a.age) // 19
a.age // 18
a.age=19 // number 19
对于原型上的可枚举属性,
Object.keys()
不会去递归获取,for in
会获取。
2 数据代理
即通过一个对象代理对另一个对象的访问和赋值!主要使用到了getter和setter
let a ={x:1}
let b= {y:2}
Object.defineProperty(a,'x',{
get(){return a.x},
set(value){a.x=value}
}
// 此时通过b对象可以对a对象x属性操作,b对象中有对a属性x的getter和setter
// a的x变化会影响b中的值,b中操作x会影响a中的x
// 两个对象关于x建立起了双向数据绑定关系
3 预编译
预编译主要注意点就是类型提升,包括var定义的函数和变量,函数和变量在用var定义时会出现类型提升,提升到当前作用域的最顶层
以下有几个注意点:
- 使用var定义的变量
var a=2
,定义部分提升 - 使用var定义的函数
var a=function(){}
,定义部分提升 - 直接定义的函数
function a(){}
,整体提升 - 提升按照顺序依次往下排列,后面的同名变量会覆盖前面的变量
示例:
function fn(a, c) {
console.log(a);
var a = 123
console.log(a);
console.log(c);
function a() { }
if (false) {
var d = 678
}
console.log(d);
console.log(b);
var b = function () { }
console.log(b);
function c() { }
console.log(c);
}
fn(1, 2)
预编译后结果为:
function fn(a, c) {
function a() { }
var d;
var b;
function c() { }
console.log(a);//function
a = 123
console.log(a);//123
console.log(c);//function
if (false) {
d = 678
}
console.log(d);//undefined
console.log(b);//undefined
b = function () { }
console.log(b);//function
console.log(c);//function
}
fn(1, 2)
输出:
[Function: a]
123
[Function: c]
undefined
undefined
[Function: b]
[Function: c]
4 函数调用中的this指向
明确一点即可:函数在与()
结合时,前面若有调用对象,则函数内this指向该对象,否则指向window
示例:
var name = 222
var a = {
name: 111,
say: function () {
console.log(this.name);
}
}
var fun = a.say
fun() // 直接调用,指向window,222
a.say() // 调用前有a对象,指向a对象,111
var b = {
name: 333,
say: function (fun) {
fun() // 传入的是函数体,然后该函数体被直接调用了,所以指向依然是window,222
}
}
b.say(a.say) // b.say调用了,b.say中this指向b,接收一个参数是函数体,然后该函数体被直接调用了,直接调用所以指向依然是window,222
b.say = a.say
b.say() // 调用前有b对象
5 Promise详解
Promise拥有3个原型方法和多个静态方法
new Promise((resolve,reject)=>{处理逻辑})
构造方法接收一个函数,该函数有两个入参用于改变promise的状态,前者为pending到ful后者为pending到rej
注意:Promise
拒绝状态如果不捕获会抛出异常!捕获方法为then
中的第二个参数回调函数或catch
方法
原型方法
-
then(回调1,回调2)
可以处理Promise被接收或拒绝的情况,最多接收两个参数,且then函数的返回值与参数有关
参数一:接收一个函数,用于Promise变为fulfilled状态时调用,该函数入参为完成值即resolve()的入参(如果入参不是函数会被转化成x=>x
)
参数二:接收一个函数,当变为rejected状态时调用,入参为拒绝原因(如果入参不是函数会被转换成Thrower函数抛出错误,抛出的值为promise的reject()的入参)
返回值:若then()函数的入参函数没有返回值如(res)=>{}
,则返回一个接收状态的Promise,入参值为undefined(等价于:Promise.resolve(undefined)
)。若返回一个值,则该值作为接收状态的promise的入参值。若抛出一个错误,则错误信息作为拒绝状态的promise的入参值(等价于:Promise.rejected(error)
)。若返回接收或拒绝状态的Promise则无需解释。 -
catch(回调)
用来处理Promise被拒绝的情况,等同于:then(undefined,onRejected)
-
finally(回调)
用于在promise结束时无论如何一定会执行的回调函数,
入参:为函数,该函数的的入参为空
返回值:为原Promise的值,finally中若抛出异常则返回rejected的Promise对象,且回调函数入参是异常对象,可以使用catch
捕获:.catch(e=>{})
静态方法
Promise.resolve()
和Promise.reject()
返回的就是成功和失败的Promise对象
-
all()
和race()
类似,都是监控多个Promise。
入参:接收一个可迭代对象,每个对象都必须为Promise,如果是常量会被Promise.resolve()
封装,
返回值:是一个新的Promise实例,当all的参数为空,返回的是成功的Promise,否则:所有成员都是成功时,为成功,且回调入参为结果数组。有一个成员为失败时,为失败,且回调入参为这个失败对象(失败对象是最先返回的那个失败对象)。 -
race()
入参:同all
返回值:当参数为空数组时,状态为pending,当参数不为空,状态为最先返回的那个Promise的状态 -
allSettled()
入参:同all
返回值:无论各项的返回为何,都将返回一个resolve状态的Promise,其回调函数的入参为一个数组,如果某项为成功返回:{"status":"fulfilled","value":"promise"}
,失败返回:{"status":"rejected","reason":"promise"}
Promise.allSettled([promise1,promise2,promise3,promise4]).then(function(args){
console.log(args);
})
/*
result:
[
{"status":"rejected","reason":"promise1"},
{"status":"fulfilled","value":"promise2"},
{"status":"fulfilled","value":"promise3"},
{"status":"rejected","reason":"promise4"}
]
*/
any()
入参:同all
返回值:除了所有Promise都返回失败这种情况会返回失败,且回调函数入参为失败对象的一个聚合(调用:.errors
获得失败结果数组),其余情况都返回最快的那个成功Promise
6 创建对象的几种方式:Object.create/new Object/Object.assign
Object.create()
:用于从原型创建对象,该对象属性为空,原型上挂载源对象的属性,原型的原型指向Object。创建的新对象的原型指向接收的参数本身。
- 接受原型对象可创建出该原型对应的对象
- 接收普通对象创建出普通对象
new Object()
:返回一个新对象,该对象属性同原对象一样
- 接受普通对象返回普通对象本身
- 接收原型对象返回原型对象本身
new XXX()
:返回XXX的新对象,该对象的原型指向构造函数原型
Object.assign()
:接收两个对象,将后者属性合并到前者,返回的对象就是第一个参数的对象,对其作了修改!
使用new创建对象。相当于执行以下步骤:
// new Person()
var Obj = {};
Obj._proto_ = Person.prototype();
Person.call(Obj);
可以通过Object.create(null)
创建一个干净的对象,也就是没有原型,而 new Object()
创建的对象是 Object的实例,原型永远指向Object的prototype
7 javascirpt字符串默认编码格式
默认采用UTF-16编码,一个字符占用2个字节,对于超过0xFFFF
的编码占用四个字节
String.length()
方法统计的是UTF-16编码单元数量!一个单元对应2字节
对于常用字符来说,一个单元长度就够了,对于超过一个编码单元,即超过两字节的是两个编码单元,即四字节。
进制转换
十进制:123
2进制:0b1010
8进制:01237
16进制:0x19FE
十进制转其他进制:
由于默认表示的数值都是十进制,所以转成其他进制使用字符串表示
调用的是Number
对象的toString(进制)
方法
var a = 11
a.toString(2) // 1011
a.toString(8)
a.toString(16)
11..toString(2) // 双点解析
(11).toString(2) // 括号解析
其他进制转十进制
调用parseInt(string,radix)
函数,默认radix=10
parseInt("1011",2) // 11
parseInt("FF",16)
parseInt("066",8) // 54
parseInt("066") // 66
8 双点解析
对于常量类型,是没有办法调用方法的,需要先解析或者参与运算,自动包装成对象才行
11.toString(2) // 报错
let a = 11
a.toString(2) // 正确
或者使用() or ..
来进行解析
(11).toString(2)
11..toString(2)
9 ?.和??运算符
?.
:用来探测当前属性是否存在
let list = res.data.list // 当data不存在时会报错
let list = res && res.data && res.data.list // 一般常用方式
let list = res?.data?.list // ?.方式
??
:用来判断当前值是否存在(除了null和undefined都是存在)
let a = a ? a : "" // a存在则为a否则为空,这里存在表示逻辑除了null、undefined、false、0其余都存在
let a = a ?? "" // a存在则为a否则为空,这里存在除了null和undefined都存在
10 Object禁止扩展preventExtensions
对一个对象禁止其新增属性:Object.preventExtensions(xxx)
此时xxx对象无法新增属性,如:xxx.a = 1
失败
11 Object密封seal
该方法将一个对象进行密封,内部实现了两个步骤:先禁止扩展,然后所有属性configurable:false
此时,这个对象不可添加新属性,且原属性的特性不能再被更改,但是属性值如果可写是可以改变的
12 Object冻结freeze
该方法冻结一个对象,内部实现两个步骤:先密封,再将所有属性writable:false,即此时对象不可添加新属性,不可重新赋值原属性值,如果想深度冻结,需要进行迭代处理。
// 深度冻结
var deepFreeze =function (obj) {
var allProps = Object.getOwnPropertyNames(obj); // 只会查找当前的对象下的所有属性,包括不可枚举
// 同上:var allProps = Object.keys(obj);
allProps.forEach(item => {
if (typeof obj[item] === 'object') {
deepFreeze(obj[item]);
}
});
return Object.freeze(obj);
}