Object对象中相关方法的介绍
Object对象本身的方法
Object的静态方法
Object.keys()
获取键,参数是一个对象,返回是一个数组。Object.keys()只能获取可枚举的属性名,此方法常用。
var arr = ['a','b','c'];
Object.keys(arr);//['0','1','2']
var obj = {
name: 'john',
age:18
};
Object.keys(obj);//['name','age']
Object.hasOwnPropertyNames()
获取属性名,接收一个对象作为参数,返回一个数组,包含了该对象自身所有的属性名。Object.hasOwnPropertyNames()返回不可枚举和枚举的属性名,可以获取继承和不可遍历的属性
var arr = ['a','b','c'];
Object.hasOwnPropertyNames(arr);//['0','1','2','length']
var obj = {
name: 'john',
age:18
};
Object.keys(obj);//['name','age']
Object.getPrototypeOf()
参数是该对象,返回该对象的原型,也是获取原型对象的标准方法
function Fn(){};
var f1 = new Fn();
Object.getPrototypeOf(f1)===Fn.prototype;//true
//特殊对象的原型
//1.空对象的原型是Object.prototype
Object.getPrototypeOf({})===Object.prototype;//true
//2.Object.prototype的原型是null
Object.getPrototypeOf(Object.prototype)===null;//true
//3.函数的原型是Function.prototype
function f(){};
Object.getPrototypeOf(f)===Function.prototype;//true
Object.setPrototypeOf()
接收两个参数,第一个参数是现有对象,第二个是是原型对象
var a = {};
var b = {x:1};
Object.setPrototypeOf(a,b);
console.log(a.x);//1
//模拟new关键字
function Fn(){
this.foo = 'foo';
}
//var f = new Fn();
var f = Object.setPrototypeOf({},Fn.prototype);
Fn.call(f);
Object.create()
一个实例对象生成另一个实例对象,接收一个对象作为参数,然后以他为原型,返回一个实例对象
var A = {
hello:function(){
console.log('hello');
}
};
var B = Object.create(A);
Object.getPrototypeOf(B);
B.hello();
Object的实例方法
Object.prototype.valueOf()
返回当前对象的值,默认情况下返回对象本身
var obj = new Object();
obj.valueOf()===obj//true
//用自定义的Object.valueOf 覆盖 Object.prototype.valueOf()
obj.valueOf = function(){
return 2;
}
//console.log(1+obj);//1[object Object]
console.log(1+obj);//3
Object.prototype.toString()
返回一个对象的字符串形式,默认返回类型的字符串
var obj2 = {a:1};
//用自定义的Object.toString() 覆盖 Object.prototype.toString()
obj2.toString = function(){
return 'hello'
}
//obj2.toString();//[object Object]
obj2.toString();//hello
Object.prototype.toLocaleString()
依赖地区,不常用。
Object.prototype.isPrototypeOf()
用来判断该对象是否是另一个对象的原型
var o1 = {};
var o2 = Object.create(o1);
var o3 = Object.create(o2);
o2.isisPrototypeOf(o3);//true
o1.isisPrototypeOf(o3);//true
Object.prototype.isPrototypeOf({});//true
Object.prototype.isPrototypeOf([]);//true
Object.prototype.isPrototypeOf(Object.create(null));//false
Object.prototype.hasOwnProperty()
接收一个字符串作为参数,返回一个布尔值,表示该实例对象自身是否具有该属性,与继承来的属性没有关系,继承来的属性返回false
var obj = {
a:123
}
obj.hasOwnProperty('a');//true
Object.prototype.propertyIsEnumerable()
判断属性是否有枚举性(可遍历),只能判断实例本身的属性,对于继承来的属性和设置不可枚举的属性一律返回false
var obj = {};
obj.a = 123;
for (var key in obj){
console.log(key);
}
obj.propertyIsEnumerable(a);//true
属性描述对象
一个对象内部的数据结构
var obj = {};
obj.name= 'john';
obj.name = 'huahua';
console.log(delete obj.name);
console.log(obj.name);
/*
{
value:huahua,
writable:true,
enumerable:true,
configurable:true,
set:undefined,
get:undefined
}*/
//获取属性描述对象
console.log(Object.getOwnPropertyDescriptor(obj,'name'));
Object.getOwnPropertyDescriptor()
可以获取属性描述对象,第一个参数是目标对象,第二个参数是一个字符串(目标对象的属性名)。不能用于继承的属性,只能用于对象自身的属性
var obj = {};
obj.name= 'john';
obj.name = 'huahua';
console.log(delete obj.name);
console.log(obj.name);
//获取属性描述对象
console.log(Object.getOwnPropertyDescriptor(obj,'name'));/*{
value:huahua,
writable:true,
enumerable:true,
configurable:true,
}*/
Object.defineProperty()
定制单个属性
//Object.defineProperty(属性所在的对象,属性名,属性描述对象)
var obj= Object.defineProperty({},'name',{
value:'john',
writable:false,//可写性
enumerable:true,//可遍历性
configurable:false//是否可配置
});
console.log(obj.name);//john
obj.name = 'huahua';
console.log(obj.name);//john,不可写
for (var key in obj){
console.log(obj[key]);//john,可遍历
}
delete obj.name;
console.log(obj.name);//john,不可配置
Object.defineProperties()
定制多个属性
var obj = Object.defineProperties({},{
p1:{
value:123,
enumerable:true,//可遍历性
},
p2:{
value:'john',
enumerable:false,
},
p3:{
get:function(){
return this.p1+this.p2
},
enumerable:true,
configurable:true//可配置
}
})
console.log(obj);
注意:
- 一旦定义了取值函数get,就不能同时定义value,否则会报错。
- 一旦定义了取值函数get,就不能同时定义writable,否则会报错。
属性描述对象中的相关属性
value
var obj = {};
obj.a = 123;
Obj.getOwnPropertyDescriptor(obj,'a').value;
Object.defineProperty(obj,'p',{
value:456,
});
console.log(obj.p);//456
writable
var obj = {};
obj.a = 123;
Object.defineProperty(obj,'p',{
value:789,
writable:false
});
console.log(obj.p);//789
obj.p=890;
console.log(obj.p);//789;
var pro = Object.defineProperty({},'foo',{
value:'a',
writable:false
});
var obj2 = Object.create(pro);
//console.log(obj2.foo);
//obj2.foo = 'b';
//console.log(obj2.foo);//a
Object.defineProperty(obj2.'foo',{
value: 'b',
});
console.log(obj2.foo);
enumerable
可遍历性
如果一旦enumerable设置了false,通常以下三个操作不会取到该属性
- for...in
- Object.keys()
- JSON.stringify()
var obj = {};
Object.defineProperty(obj,'foo',{
value:123,
enumerable:false
});
console.log(obj.foo);
for (var key in obj){
console.log(obj[key])
}
console.log(Object.keys(obj));//[]
console.log(JSON.stringify(obj));//{}
注意:
for...in循环可以遍历继承来的属性
function B(){
this.name = 'john'
}
function A(){
B.call(this)
}
var c = new A();
console.log(c.name);//john
for (var key in c){
console.log(c[key]);//john
}
//Object.keys()可以获取继承来的属性
Object.keys(c);//['name']
configurable
是否可配置,决定是否可以修改属性描述对象。
注意:
- 一旦设置configurable为false,属性描述对象value,writable,enumerable,configurable都不能被修改,也不能删除属性。
- writable只有在false改为true的时候会静态失败,true改为false会允许
- 只要writable和configurable中有一个为true,就允许被修改
var obj = {};
Object.defineProperty(obj,'a',{
value:4,
writable:false,
enumerable:false,
configruable:false
});
console.log(obj);
obj.a = 3;
console.log(obj.a);
存取器
var obj = Object.defineProperty({},'p',{
get:function(){
return 'getter'
},
set:function(value){
console.log('setter:'+value)
}
});
obj.p;//getter
obj.p = 123;
//简便写法
var obj = {
get p(){
return "getter";
},
set p(value){
console.log('setter:'+value);
}
}
console.log(obj.p);
obj.p = 123;
浅拷贝
//基本数据类型:按值传递
var a = 1;
var b = a;
b = 100;
console.log(b);//100
console.log(a);//1
//引用数据类型:按引用地址传递
var arr = [1,2,3];
var newArr = arr;
newArr.push(4);
console.log(newArr);//[1,2,3,4]
console.log(arr);//[1,2,3,4]
拷贝:浅拷贝和深拷贝
操作拷贝之后的对象的某个属性不会影响原始对象中的属性,这种拷贝就称为深拷贝,反之,有影响叫浅拷贝。
var obj = {
name:'john',
age:20,
hobby:'eat',
gildfriend:{
name:'huahua',
age:18,
hobby:'eat'
}
};
function shadowCopy(toObj,fromObj){
//实现浅拷贝
for (var key in fromObj){
toObj[key] = fromObj[key];
}
return toObj;
}
var newObj = shadowCopy({},obj);
newObj.age = 30;
newObj.girldfriend.hobby = 'sleep';
浅拷贝不是直接赋值,浅拷贝新建了一个对象,将原来对象的属性都一一复制过来,复制的是值,而不是引用。浅拷贝只是复制了第一层的属性,并没有递归所有的值复制过来
深拷贝
对目标对象的完全拷贝,不像浅拷贝只是复制了一层的引用,就连值也复制过来。只要进行了深拷贝,他们是老死不相往来,谁也不影响谁。
var obj = {
name:'john',
age:20,
hobby:['eat','song'],
gildfriend:{
name:'huahua',
age:18,
hobby:'eat',
friend:{
name:'xinxin',
age:23,
hobby:'money'
}
}
};
function deepCopy(to,from){
//遍历from对象的所有的的属性,copy到to对象中
for (var key in from){
//不遍历原型链上的属性
if(from.hasOwnProperty(key)){
//如果值是对象并且有值,继续遍历
if(from[key]||typeof from[key]==='object'){
//区分是一般对象还是数组
to[key] = from[key].constructor === Array?[]:{};
console.log(to[key]);
to[key] = deepCopy(to[key],from[key]);
}
//如果不是,直接赋值
else{
to[key] = from[key];
}
}
}
return to;
}
var newObj = deepCopy({},obj);
console.log(newObj);
newObj.friend.name = '小红';
console.log(newObj);
模块的基本实现
简单的说一个js文件就是一个模块
<script src="module.js"></script>
<script>
module.m1();//m1
module.m2();//m2
</script>
var module = (function(){
var count = 0;
var m1 = function(){
console.log('m1');
//...
};
var m2 = function(){
console.log('m2');
//...
};
return{
m1:m1,
m2:m2
}
})();
放大模式
<script src="module.js"></script>
<script>
module.m1();//m1
module.m2();//m2
console.log(module);
</script>
var module = (function(){
var count = 0;
var m1 = function(){
console.log('m1');
//...
};
var m2 = function(){
console.log('m2');
//...
};
return{
m1:m1,
m2:m2
}
})();
(function(mod){
module.m3 = function(){
console.log('m3')
}
return mod;
})(module);
宽放大模式
最终写法
...
(function(mod){
module.m3 = function(){
console.log('m3')
}
return mod;
})(window.module||{});
命名空间
作用:
全局作用域下,避免变量的污染
<script src='namespace.js'></script>
<script src='namespace_sub.js'></script>
<script>
console.log(namespace);
var p1 = new namespace.PersonInfo({name:'john',gender:'男'});
console.log(p1);
namespace.personInfoUtil.show(p1);
var helloStr = p1.getHello();
console.log(helloStr);
var c = new namespace.sub.Cat('huahua','白色');
c.sleep();
</script>
//个人信息类
//姓名 性别
var namespace = function(namespace){
//声明了一个顶层的命名空间
//个人信息类:构造函数构建对象
namespace.PersonInfo = function(obj){
obj = obj||{};
this.name = obj.name||"";
this.gender = obj.gender||"?";
}
namespace.PersonInfo.prototype.getApplication = function(){
var str = '';
if(this.gender === '男'){
str = '男士';
}else{
str = '女士';
}
return str;
}
namespace.PersonInfo.prototype.getHello = function(){
var s = 'hello'+this.name+this.getApplication();
return s;
}
//个人信息工具类
namespace.personInfoUtil = function(){
return {
//p形参是代指哪个对象
show:function(){
alert('姓名:'+p.name,'性别:'+p.gender)
}
}
}();
return namespace;
})(window.namespace||{});
//动物园
namespace.sub = (function(sub){
//定义了一个子命名空间
//动物类
sub.Animal = function(name,color){
this.name = name;
this.color = color;
};
sub.Animal.prototype.sleep = function(){
console.log('睡懒觉')
}
//猫类
sub.Cat = function(name,color){
//继承属性
sub.Animal.call(this,name,color);
}
//继承方法
sub.Cat.prototype = Object.create(sub.Animal.prototype);
sub.Cat.prototype.constructor = sub.Animal;
return sub;
})(window.namespace.sub||{});