获取Object的属性可以通过Object.key或者for in语句去获取,获取到的属性都是可枚举属性。
<script>
var obj = {name: 'David'};
obj.toString = 1;
//在IEbug情况下,obj.toString依然是输出1,但是这个属性是不可枚举的,通过Object.keys找不到
console.log(obj.toString);
</script>
var _ = {};
_.isObject() = function(object) {
return toString.call(object) === "[object Object]";
};
var hasOwnProperty = Object.hasOwnProperty;
_.has = function(object, key) {
return object != null && hasOwnProperty.call(object, key);
};
// 判断是否有bug,对象{toString: 1}的自身属性toString,应该是一个可枚举属性;如果不是,则表明是bug
// {toString: 1}.toString 的值依然是1,只是toString属性不可枚举,找不到这个属性了;
var hasEnumBug = ({toString: 1}).propertyIsEnumable(toString) === false;
var properties = ["constructor", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "toLocaleString", "toString","valueOf"];
// keys
_.keys = function(object) {
var result = [];
if(!_.isObject(object)) {
return result;
}
// 有bug的处理
if(hasEnumBug) {
for(var i; i< properties.length; i++) {
var prop = properties[i];
// object原型上的的属性被修改过后,object[prop]就不等于原型上的属性
if(object[prop] !== Object.prototype[prop]) {
result.push(prop);
}
}
}
//keys
if(Object.keys) {
return Object.keys(object);
}
// for in
for(var key in object) {
result.push(key);
}
return result;
};
例子1, 2, 3:
- 怎样监听对象属性的变化;
- 函数缓存;
监听数组对象的变化;
//原型链
// 代理原型, Vue,响应式系统
// 例子1
var obj = {};
Object.defineProperty(obj, 'name', {
get() {
console.log('111111');
},
set(value) {
console.log(value);
}
});
obj.name = 'David';
// 例子2
function fn() {
console.log('111');
}
var wait = fn;
fn = function() {
console.log('000');
wait();
};
fn();
// 例子3: 代理原型,检测数组变化
var ProxyMethods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort'];
var arrProto = Array.prototype;
var obj = Object.create(arrProto);
ProxyMethods.forEach((method) => {
obj[method] = function() {
console.log('我检测到了' + method);
var ret = arrProto[method].apply(this, arguments);
return ret;
};
});
var arr = [];
arr.__proto__ = obj;
arr.push(11);
console.log(arr);
arr.push(8);
arr.push(7);
arr.sort(function(a, b) {
return a - b;
});
console.log(arr);
createAssigner:
// 判断是否有bug,对象{toString: 1}的自身属性toString,应该是一个可枚举属性;如果不是,则表明是bug
// {toString: 1}.toString 的值依然是1,只是toString属性不可枚举,找不到这个属性了;
var hasEnumBug = ({toString: 1}).propertyIsEnumerable('toString') === false;
var properties = ["constructor", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "toLocaleString", "toString","valueOf"];
// keys:获取object上所有的属性(自身可枚举属性)
_.keys = function(object) {
var result = [];
if(!_.isObject(object)) {
return result;
}
//判断浏览器是否支持Object.keys,优先使用Object.keys
if (Object.keys) {
return Object.keys(object);
}
// for in
for(var key in object) {
result.push(key);
}
// 有bug的处理
if(hasEnumBug) {
for(var i; i< properties.length; i++) {
var prop = properties[i];
// object原型上的的属性被修改过后,object[prop]就不等于原型上的属性
if(object[prop] !== Object.prototype[prop]) {
result.push(prop);
}
}
}
return result;
};
// allKeys:获取object上所有的属性(自身可枚举属性 + 原型链上可枚举的属性)
_.allKeys = function(object) {
var result = [];
if(!_.isObject(object)) {
return result;
}
// for in
for(var key in object) {
result.push(key);
}
// 有bug的处理
if(hasEnumBug) {
for(var i; i< properties.length; i++) {
var prop = properties[i];
// object原型上的的属性被修改过后,object[prop]就不等于原型上的属性
if(object[prop] !== Object.prototype[prop]) {
result.push(prop);
}
}
}
return result;
};
var createAssinger = function(func){
return function(obj) {
var length = arguments.length;
//
if (length < 2 || obj == null) {
return obj;
}
for (var i=1; i<length; i++) {
//获取第二个参数
var source = arguments[i];
var keys = func(source);
var sLength = keys.length;
for (var j=0; j < sLength; j++) {
var key = keys[j];
obj[key] = source[key];
}
}
return obj;
};
};
_.extend = createAssinger(_.allKeys);
_.extendOwn = createAssinger(_.keys);