获取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);}}}//keysif(Object.keys) {return Object.keys(object);}// for infor(var key in object) {result.push(key);}return result;};
例子1, 2, 3:
- 怎样监听对象属性的变化;
- 函数缓存;
监听数组对象的变化;
//原型链// 代理原型, Vue,响应式系统// 例子1var obj = {};Object.defineProperty(obj, 'name', {get() {console.log('111111');},set(value) {console.log(value);}});obj.name = 'David';// 例子2function 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.keysif (Object.keys) {return Object.keys(object);}// for infor(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 infor(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);
