_.isEqual()
1 .判断两个值是否相等
2 .深度进行判断
_.isMatch()
1 .深度搜索是否有某个值
_.isOlainObject(value)
1 .检查value是否是普通对象,也就是该对象由Object 构造函数创建,或者[[Prototype]]为空
2 .
_.toPlainObject()
1 .转换为普通对象,甚至对象继承的可枚举属性也一并继承
2 .
assign()
1 .对象合并,但是原生的方法是只会进行浅复制,如果源对象的某个属性的值是对象,那么目标拷贝的是这个对象的引用。
2 .只拷贝源对象自身的属性,不拷贝继承属性,也不拷贝不可枚举的属性
let b1={
'name':123
}
let o1={
'name':b1
}
let o2={
'age':20
}
cc(o1)
b1.name='asdfasd'
cc(Object.assign(o1,o2))
1 .可以发现,当修改b1的时候,后面合并的的数组还是会发生变化,那这样就很麻烦了。要不就是保证后面的数组在合并之后被冻结,不然永远不能保证这个数据是固定的
2 .自己写一个合并的函数,是深度遍历合并的
3 .在合并之前,合并的是克隆之后的函数,这样原来怎么改都不会影响到现在的数组了。
let b1={
'name':123
}
let o1={
'name':b1
}
let o2={
'age':20
}
cc(o1)
let xx=Object.assign(o2,_.cloneDeep(o1))
cc(xx)
b1.name='asdfasd'
cc(o1)
cc(xx)
3 .拷贝继承链 _.assignIn:类似于assign,但是会遍历并继承来源对象的属性
function clone(origin){
let originProto=Object.getPrototypeOf(origin)
return Object.assign({},originProto, origin);
}
function assign(obj,arr){
let re=Object.assign({},obj)
for (let i of arr){
Object.assign(re,clone(i))
}
cc(re)
return re
}
assign({},[new f11,new foo])
4 ..assignWith():拷贝选项参数,在遍历的时候先检查属性值,如果属性值不符合给定的约定函数,那么不进行合并
5 ..at(object, [paths])
1 .如果是选object里面的数据的话,数组的参数是要要选的数据的路径
var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
c(_.at(object,['a[0].b.c'],'a[1]'))
let arr=['a','f','c']
c(_.at(arr,2))
2 .如果选的arr里面的数据的话,参数是数组内的索引
create() :创建一个继承对象的对象
1 .这个直接使用es6语法实现,非常简单
2 .这个不能写成调用函数,应该始终使用语法来实现,因为super的时候需要继承上个对象的属性,这个如果把要继承的对象按照一个函数的参数传进去的话,是无法得到这个东西的
3 .子类必须在sonstructor中调用super方法。子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后对其进行加工,加上子类自己的实例属性和方法,如果不调用super方法,子类就得不到this对象
4 .ES5继承方式:先创建子类的实例对象this,然后将父类的方法添加到this上面
5 .ES6继承机制:先将父类实例对象的属性和方法,添加到this上面,然后在根据子类的构造函数修改this.
1 .所以可以继承原生构造函数定义子类,可以继承父类的所有行为
2 .es6可以自定义原生的数据结构(Array,String)的子类
3 .extends关键字不仅可以继承类,还可以继承原生的构造函数
6 .super
1 .super最为函数调用,代表父类的构造函数,用在子类继承的时候。
class Shape{
constructor(x,y){
this.x=x
this.y=y
}
p(){
return '2'
}
p2(){
return this.x
}
}
class Circle extends Shape{
constructor(x,y,color){
super(x,y)
// 调用父类的constructor(x,y),
// super虽然代表的是父类的构造函数,但是返回的是子类的实例,super内部的this指的是当前的子类
this.color=color;
// console.log(super.x)
// 指向父类的原型对象,所以定义在父类实例上的方法或者属性是无法通过super调用的--返回undefined
// console.log(super.p2())
// 可以通过这样的拐弯来实现可以访问。其实访问的是Shape.prototype.p()
// 也就是说上面的x属性如果这样定义的话,是可以获取到的
}
tostring(){
console.log(super.p2())
// 在子类普通方法内使用super,内部的this指向当前的子类实例
}
}
const c1=new Circle(10,10,'red')
2 .super作为对象时,在普通方法中,指向父类的原型对象,在静态方法中,指向父类
3 .由于this指向子类实例,如果不用this,而是使用super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性
4 .
7 .类的prototype属性与proto属性(表示继承,或者说谁给了他这个属性)
1 .子类的__proto__属性,表示构造函数的继承,总是指向父类
2 .子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性
3 .
class b extends Object{}
// 子类继承Object类
cc(b.__proto__==Object)
cc(b.prototype.__proto__==Object.prototype)
class bb{}
// 子类什么都继承,就是个普通函数
cc(bb.__proto__==Function.prototype)
// 此时子类就是一个普通函数,所以直接继承自Function.prototype
cc(bb.prototype.__proto__==Object.prototype)
// bb调用之后返回一个空对象,所以指向构造函数Object的prototype属性
4 .实例的proto属性:唯一作用,可以通过子类实例来修改父类实例的行为
class a{
constructor(x){
this.x=x
}
}
class aa extends a{
constructor(x){
super(x)
}
}
const a1=new a('10')
const a2=new aa()
cc(a2.__proto__.__proto__==a1.__proto__)
cc(a2.__proto__)
//aa{}
cc(a2.__proto__.__proto__)
// a{}
a2.__proto__.__proto__.say=function(){
console.log('sasasa')
}
a2.say()
a1.say()
.defaults(object, [sources]),.defaultsDeep(object, [sources])
1 .分配来源对象的可枚举属性到目标对象所有解析为 undefined 的属性上。 来源对象从左到右应用。 一旦设置了相同属性的值,后续的将被忽略掉。
2 .Object.assign()方法不能实现的东西
1 .对于object.assign来说,如果第一个参数不是对象的话,则会先转会对象
2 .对于非首参数出现非对象,如果不能转换为对象,都是会跳过的。
3 .拷贝得属性是有限制得,只能拷贝源对象的自身属性,不拷贝不可枚举的属性enumerable:false
4 .浅拷贝:如果源对象某个属性的值是对象,那么目标对象拷贝的是这个对象的引用.lodash 的defaultsDeep实现了这个操作,可以合并拷贝新的对象。
5 .同名属性的替换:嵌套的对象,遇到同名属性,是替换,而不是添加
const target = { a: { b: 'c', d: 'e' } }
const source = { a: { b: 'hello' } }
let o2=_.defaultsDeep({},target,source)
cc(o2)
//{ a: { b: 'c', d: 'e' } }
//注意在嵌套数组的合并中,也是按照外面的策略,如果原来有的话,就不再添加后面的了。
//解决的是object.assign方法整个替换a后面的情况
6 .取值函数的处理:只能进行值的复制,如果要复制的是一个取值函数,那么求值之后进行复制
7 .
findKey()
1 .按照value的属性来进行条件选择,返回整个key-vallue键值对
.forIn(object, [iteratee=.identity]):遍历对象的自身和继承的可枚举属性
1 .也是无法保证遍历的顺序
_.forOwn:遍历自身的可枚举属性
1 .也是无法保证遍历顺序
_.functions:返回一个function对象自身可枚举属性名的数组
_.functionsIn:返回一个function对象和继承的可枚举属性名的数组
_.get(object, path, [defaultValue]):根据对象路径获取值。如果解析value是undefined会以defaultValue取代
_.has(object,path):检查path是否是对象的直接属性
1 .返回对象的所有属性,然后进行数组的检查
2 .直接使用in 语法
_.invert(obj):反转对象的key和value
1 ..invertBy(obj,fn):传入两个参数,反转对象的key和value,并且在反转的时候对key进行处理
2 ..invertByAll(obj,fn1,fn2):传入3隔参数,反转对象的key和val,并且在反转的时候同时对key,value进行处理
let obj={
'name':'libater',
'age':20
}
cc(_.invert(obj))
cc(_.invertBy(obj,(k)=>{
return 'change'+k
}))
一些按照路径选择key,value的函数
1 ._.invoke(object, path, [args])
2 .
_.keys()
1 .创建object自身可枚举属性名为一个数组(非对象的值会被强制转换为对象)
2 ..keysIn()创建object自身或继承的可枚举属性名为一个数组
3 ..mapKeys()这个方法创建一个对象,对象的值与源对象相同,但 key 是通过 iteratee 产生的。
4 ..mapValues()创建一个对象,对象的key相同,值是通过 iteratee 产生的。 iteratee 会传入3个参数: (value, key, object)
5 ..values()
6 ._.valuesIn()
_.merge()
1 .递归合并来源对象的自身和继承的可枚举属性到目标对象,跳过来源解析为undefined的属性,数组和普通对象会递归合并,其他对象和值会被直接分配。来元对象从左到右分配,后续的来源对象属性会覆盖之前分配的属性
2 ..mergewith(object, sources, customizer):类似于merge,但是接收一个参数决定如何合并,如果customizer返回undefined将会由合并处理方法代替
3 ..
_.omit(object, [props])
1 .返回忽略属性之外的自身和继承的可枚举属性。就是删去括号里面的属性
2 .这个方法其实很弱智啊。自己写的话很简单啊
3 ..omitBy(object, [predicate=.identity])进过predicate判断是不是真值的属性和自身和继承的可枚举属性
4 ._.
_.pick(object, [props])
1 .从一个对象选出选中属性的对象
3 .pickBy(object, [predicate=.identity]):类似上面的东西
_.result(object, path, [defaultValue])
1 .除了如果解析得到的值是一个函数的话,就绑定this到这个函数并返回执行后的结果。
2 .
_.set(object, path, value)
1 .设置值到对象对应的属性路径上,如果没有则创建这部分路径。 缺少的索引属性会创建为数组,而缺少的属性会创建为对象
2 ._.unset(obj,path):移除对象路径的属性
_.toPairs(obj)
1 .创建一个对象自身可枚举属性的键值对数组
2 ._.toPaireIn():创建一个对象自身和继承的可枚举属性的键值对数组