基本描述
语法
Object.values(obj)
参数
- obj 想要返回自身可枚举属性值的对象
返回值
一个数组,数组的值由obj的自身可枚举属性值组成。
polyfill
这个方法返回一个对象自身可枚举属性值,看到这个描述会不会想起Object.keys的描述,前者返回的是值,后者返回的是键。那为啥后者早就成为规范了前者还在草案阶段。言归正传,想要对Object.values进行polyfill,最简单的方案就是把Object.keys的polyfill拿过来改改就行了。但是那段代码有点长,我们可以直接利用Object.keys的结果。
if(!Object.values){
Object.values = function(obj){
obj = Object(obj);
var keys = Object.keys(obj);
var length = keys.length;
var values = [];
for(var i=0;i< length;i++){
values[i] = obj[keys[i]];
}
return values;
}
}
在underscore.js中,_.values也是使用了相同的思路。
const reduce = Function.bind.call(Function.call, Array.prototype.reduce);
const isEnumerable = Function.bind.call(Function.call, Object.prototype.propertyIsEnumerable);
const concat = Function.bind.call(Function.call, Array.prototype.concat);
const keys = Reflect.ownKeys;
if (!Object.values) {
Object.values = function values(O) {
return reduce(keys(O), (v, k) => concat(v, typeof k === 'string' && isEnumerable(O, k) ? [O[k]] : []), []);
};
}
虽然这个polyfill我不是很推荐但是其中包含的知识量还是挺丰富的。
首先这是ES6的语法,我准备转述一下
if(!Object.values){
Object.values = (function(){
var reduce = Function.bind.call(Function.call, Array.prototype.reduce);
//var reduce = Function.call.bind(Array.prototype.reduce);
var isEnumerable = Function.bind.call(Function.call, Object.prototype.propertyIsEnumerable);
var concat = Function.bind.call(Function.call, Array.prototype.concat);
var keys = Reflect.ownKeys;
return function(obj){
return reduce(keys(obj),function(v,k){
return concat(v,typeof k === 'string' && isEnumerable(obj,k)?[obj[k]]:[] );
},[]);
}
})();
}
第一个问题,为什么会有Function.bind,bind方法不是在Function.prototype上吗?这个问题还是蛮复杂的。首先,一个正常的函数,它有一个prototype属性指向一个对象。其次,一个对象(一般情况蛤),它会有一个内部属性[[prototype]],指向这个对象的构造函数的prototype。最后,Function即是一个函数也是一个对象,它的prototype和[[prototype]]指向的是同一个对象。Function.bind是把Function看成是一个对象,通过原型链访问到了bind方法。
第二个问题,bind方法在这里起到了什么作用?答案是制造偏函数。
第三个问题,两个call起到了什么作用?Function.bind.call这个call我不太理解,因为Function.call本来就可以访问到bind方法,所以可以直接写成var reduce = Function.call.bind(Array.prototype.reduce);。Function.call的call被转移到了偏函数中,以reduce为例,调用的时候相当于Array.prototype.reduce.call,就是为了不在返回的匿名函数中显示调用call所使用的语法糖。感觉炫技的成分更多一点,这个使用方法可以学一学。
第四个问题是Reflect.ownKeys,我们暂时可以把它当成Object.getOwnPropertyNames。
最后的问题就是reduce实现了,其实这里用each之类的都可以,实现上并没有什么太复杂的,自己看吧。