自己参考用Object

75 阅读5分钟

参考阮一峰的javascript教程

javascript的对象都继承自Object对象,那些对象都是Object的实例 Object对象的原生方法分为自身的方法(静态方法)和实例方法

1.Object本身方法就是直接定义在Object对象上的方法

Object.print = function(o){console.log('a')}

2.Object的实例方法就是定义在Object.prototype上的方法,可以被Object的实例直接使用,凡是在Object.prototype上定义的属性和方法,将被所有实例对象共享

Object.prototype.print2 = function(){console.log(this)}
var obj = new Object()
//obj直接继承了Object.prototype的属性和方法
//obj对象的print2方法实质上就是调用Object.prototype.print2
obj.print2() //object

    Object.create1 = function(){
      console.log(this);
      console.log('自身方法/静态方法');
    }
    Object.prototype.create2 = function(){
      console.log(this);
      console.log('实例方法');
    }
    var obj = new Object() //等价于var obj = {}
    obj.create2(); //{} 实例方法
    Object.create1(); //ƒ Object() { [native code] }  自身方法/静态方法
    obj.create1(); //Uncaught TypeError: obj.create1 is not a function

instanceof运算符用来验证,一个对象是否为指定的构造函数的实例

Object()参数是原始值类型将转换为对应的包装对象,如果参数是对象,则会返回该对象本身,不转换

var obj = new Object(1)
obj instanceof Object //true
obj instanceof Number //true

var obj2 = new Object('foo')
obj2 instanceof Object //true
obj2 instanceof String //true

var obj = Object(true);
obj instanceof Object // true
obj instanceof Boolean // true

var arr = [];
var obj = Object(arr); // 返回原数组
obj === arr // true

var value = {};
var obj = Object(value) // 返回原对象
obj === value // true

var fn = function () {};
var obj = Object(fn); // 返回原函数
obj === fn // true

//所以可以用这个函数判断变量是否是一个对象
function isObject(obj){
	return obj === Object(obj);
}
isObject([]) //true
isObject({}) //true

Object不仅可以当作工具函数使用,还可以当作构造函数使用,即前面使用new命令

var o1 = {a: 1};
var o2 = new Object(o1);
o1 === o2 // true

var obj = new Object(123);
obj instanceof Number // true

Object(value)是将value转成一个函数 new Object(value)表示新生成一个对象,值是value

Object.keys(obj)(常用)和Object.getOwnPropertyName(obj) 都是返回自身的所有属性名(不包括继承的) Object.getOwnPropertyName可返回不可枚举属性,Object.keys不行,下面length是不可枚举属性

var a = ['Hello', 'World'];
Object.keys(a) // ["0", "1"]
Object.getOwnPropertyNames(a) // ["0", "1", "length"]
Object.keys([]) // []
Object.getOwnPropertyNames([]) // [ 'length' ]
Object.keys(Object.prototype) // []
Object.getOwnPropertyNames(Object.prototype)
// ['hasOwnProperty',//  'valueOf',//  'constructor',//  'toLocaleString',//  'isPrototypeOf',//  'propertyIsEnumerable',//  'toString']

如果一个属性的enumerable为false,下面三个操作不会取到该属性。 for..in循环 Object.keys方法 JSON.stringify方法

原型链相关方法 Object.create():该方法可以指定原型对象和属性,返回一个新的对象。 如果原型对象的某个属性的writable为false,那么子对象将无法自定义这个属性。

var proto = Object.defineProperty({}, 'foo', {
  value: 'a',
  writable: false
});

var obj = Object.create(proto);

obj.foo = 'b';
obj.foo // 'a'

proto是原型对象,它的foo属性不可写。obj对象继承proto

Object.getPrototypeOf():获取对象的Prototype对象,原型

var o1 = new Object();
o1.toString() // "[object Object]"
var o2 = {a:1};
o2.toString() // "[object Object]"

数组、字符串、函数、Date 对象都分别部署了自定义的toString方法,覆盖了Object.prototype.toString方法

[1, 2, 3].toString() // "1,2,3"

'123'.toString() // "123"

(function () {
  return 123;
}).toString()
// "function () {
//   return 123;
// }"

(new Date()).toString()
// "Tue May 10 2016 09:11:31 GMT+0800 (CST)"

上面代码中,数组、字符串、函数、Date 对象调用toString方法,并不会返回[object Object],因为它们都自定义了toString方法,覆盖原始方法。其中第二个Object表示该值的构造函数,这是一个十分有用的判断数据类型的方法。

由于实例对象可能会自定义toString方法,覆盖掉Object.prototype.toString方法,所以为了得到类型字符串,最好直接使用Object.prototype.toString方法。通过函数的call方法,可以在任意值上调用这个方法,帮助我们判断这个值的类型。

Object.prototype.toString.call(value) 上面代码表示对value这个值调用Object.prototype.toString方法。

不同数据类型的Object.prototype.toString方法返回值如下。

数值:返回[object Number]。 字符串:返回[object String]。 布尔值:返回[object Boolean]。 undefined:返回[object Undefined]。 null:返回[object Null]。 数组:返回[object Array]。 arguments 对象:返回[object Arguments]。 函数:返回[object Function]。 Error 对象:返回[object Error]。 Date 对象:返回[object Date]。 RegExp 对象:返回[object RegExp]。 其他对象:返回[object Object]。 这就是说,Object.prototype.toString可以看出一个值到底是什么类型。

Object.prototype.toString.call(2) // "[object Number]"
Object.prototype.toString.call('') // "[object String]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(Math) // "[object Math]"
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call([]) // "[object Array]"

利用这个特性,可以写出一个比typeof运算符更准确的类型判断函数。

var type = function (o){
  var s = Object.prototype.toString.call(o);
  return s.match(/\[object (.*?)\]/)[1].toLowerCase();
};

type({}); // "object"
type([]); // "array"
type(5); // "number"
type(null); // "null"
type(); // "undefined"
type(/abcd/); // "regex"
type(new Date()); // "date"

在上面这个type函数的基础上,还可以加上专门判断某种类型数据的方法。

var type = function (o){
  var s = Object.prototype.toString.call(o);
  return s.match(/\[object (.*?)\]/)[1].toLowerCase();
};

['Null',
 'Undefined',
 'Object',
 'Array',
 'String',
 'Number',
 'Boolean',
 'Function',
 'RegExp'
].forEach(function (t) {
  type['is' + t] = function (o) {
    return type(o) === t.toLowerCase();
  };
});

type.isObject({}) // true
type.isNumber(NaN) // true
type.isRegExp(/abc/) // true

typeof运算符用于判断对象的类型 typeof可以判断的类型有: string,number,boolean,undefined,object(null也是object中的),symbol,function

instanceof运算符用来验证,一个对象是否为指定的构造函数的实例 判断该实例是否为某个对象的实例

Object.prototype.hasOwnProperty方法接受一个字符串作为参数,返回一个布尔值,表示该实例对象自身是否具有该属性

var obj = Object.defineProperty({}, 'p', {
  get: function () {
    return 'getter';
  },
  set: function (value) {
    console.log('setter: ' + value);
  }
});

obj.p // "getter"
obj.p = 123 // "setter: 123"

上面代码中,obj.p定义了get和set属性。obj.p取值时,就会调用get;赋值时,就会调用set。

JavaScript 还提供了存取器的另一种写法。

// 写法二

var obj = {
  get p() {
    return 'getter';
  },
  set p(value) {
    console.log('setter: ' + value);
  }
};

上面两种写法,虽然属性p的读取和赋值行为是一样的,但是有一些细微的区别。第一种写法,属性p的configurable和enumerable都为false,从而导致属性p是不可遍历的;第二种写法,属性p的configurable和enumerable都为true,因此属性p是可遍历的。实际开发中,写法二更常用。

var obj ={
  $n : 5,
  get next() { return this.$n++ },
  set next(n) {
    if (n >= this.$n) this.$n = n;
    else throw new Error('新的值必须大于当前值');
  }
};

obj.next // 5

obj.next = 10;
obj.next // 10

obj.next = 5;
// Uncaught Error: 新的值必须大于当前值

上面代码中,next属性的存值函数和取值函数,都依赖于内部属性$n。