从零开始学前端 - 16. JS对象Object介绍及常用方法

作者: 她不美却常驻我心
博客地址: https://blog.csdn.net/qq_39506551
微信公众号:老王的前端分享
每篇文章纯属个人经验观点,如有错误疏漏欢迎指正。转载请附带作者信息及出处。

  对象这一概念是初学者比较难以理解的点,理论性的东西较多,而且需要理解的思想也不少,所以初学者可以先将对象理解成一种特殊的数据存储方式,再慢慢理解。

一、什么是对象

  对象 Object 是 JS 的一种特殊的基本数据类型。有一句话非常的有名,叫做 万物皆对象 ,也就是说,JS 中的所有事物都是对象,包括字符串、数字等。

var str = "字符串";	// 实际上创建了一个新的字符串对象,继承了 String 对象的属性和方法。
console.log(str.__proto__);	// 指向 String 对象

   对象 Object 可以看做是拥有属性和方法的数据。我们来举个生活中的例子来详细说明什么是对象:

   我们将动物 Animal 看做是一个类,而狗 dog 是属于动物这个类中的一个对象,狗的名字、年龄、性别可以看做是它的属性,而它会跑、会吃东西这些动作行为,可以看做是它的方法。( 类 + 对象 的形式是面向对象编程的基础,初学者可以慢慢理解)

var dog = {
	name : "旺财",
	age : "3",
	sex : "公",
	run : function(){
		console.log("跑");
	},
	eat : function(){
		console.log("吃");
	}
};

   我们简单的介绍了一下什么叫做对象,并且通过代码将它的属性和方法描述了出来,对象可以看做是属性方法的集合,通过键值对的方式储存起来,每个键名为这个对象的属性名和方法名。
   然而对象并不只是一种数据存储方式,在 JS 中,它是一个极为特殊的存在,因为它除了这些属性外,还从原型对象上继承了一些属性和方法,对象的属性通常都是继承的属性。这种从原型上继承的行为,也是 JS 的核心特征。

  Object同时也是一种复合类型的数据,可以将很多的数据通过键值对的形式表示出来。接下来我们通过对象的方式来对数据进行存储:

var obj = {
	author_name : "她不美却常驻我心" ,
	Wechar : "老王的前端分享", 
	"author age" : 18,
	"标题" : "从零开始学前端" ,
	"if" : "使用关键字命名"
}

  键名通常是字符串类型的数据,符合 JS 的命名标准。任何的字符都可以通过增加引号来作为对象的键名,但我们并不推荐使用中文字符、保留关键字等不符合命名规范的特殊的方式进行命名,比如说例子中的"键名"、"if"
  符合命名规范的字符可以直接作为对象的键名,不需要添加额外的引号,而对象的值可以是任意数据类型。

二、对象的方法

1. 创建对象

  • 直接创建
var obj = {};
  • 通过构造函数创建
var obj = new Object();		// 等同于 var obj = {};
  • 通过对象方法创建
var obj = Object.create();

2. 访问对象

var obj = {
	a : 1,
	"特殊键名" : 2
}
  • 对象名 + “.” + 属性名 (ObjectName.propertyName)
obj.a;			// 1
obj.特殊键名		// 2	特殊键名采用这种方式访问在低版本浏览器中会报错
  • 对象名 + " [ " + " 特殊属性名" + " ] " (ObjectName[“propertyName”];
obj["a"];			// 1
obj["特殊键名"];		// 2

  一般我们采用第一种方式来访问对象的属性,当属性名为中文等特殊情况时,可以使用第二种方式来访问。

3.对象的增删改查

3.1 增加属性
var obj = {};
obj.a = 1;

// 为 Object 添加新方法
Object.prototype.addObject = function (key, value) {
	this[key] = value;
	return this;
}
obj.addObject("test",3);		// {a : 1, test : 2}
3.2 删除属性
var obj = { a : 1 };
delete obj.a;
3.3 修改对象属性
var obj = { a : 1 };
obj.a = 2 ;

// 重新定义已经拥有的方法
Object.prototype.create = function(){
	// do something
}

3.4 查找对象属性
var obj = {
	a : 1,
	"特殊键名" : 2
}
  • 使用循环遍历对象:
for (var key in obj) {
    console.log(key);		// a , 特殊键名
    console.log(obj[key])	// 1 , 2
}
// 按照对象属性的顺序依次打印。
  • 使用对象内置方法:Object.keys()
var keys = Object.keys(obj);
console.log(keys);		["a" , "特殊键名"];
// 返回一个包括对象内可枚举属性以及方法名称的数组
  • 使用对象内置方法:Object.getOwnPropertyNames()
var keys = Object.getOwnPropertyNames(testObj);
console.log(keys);
// 返回一个指定对象所有自身属性的属性名的数组
3.5 检查对象中是否存在属性
  • 使用运算符 in
    如果对象的属性或者继承属性中
var obj = { a : 1 };
"a" in obj;		// true
"b" in obj;		// false
"valueOf" in obj	// true	 obj 继承了 Object 对象原型链上的方法。
  • 使用内置方法 Object.hasOwnProperty()
obj.hasOwnProperty("a");	// true
obj.hasOwnProperty("valueOf");	// false
  • 使用内置方法 Object.propertyIsEnumerable
obj.propertyIsEnumerable("a");	// true
obj.propertyIsEnumerable("valueOf");	// false

4. 内置方法

4.1 Object.assign() 复制对象的可枚举属性

  语法:Object.assign(target, source...)
  作用:将对象的可枚举属复制到目标对象,并返回目标对象。
  实例:

var obj1 = {};
var obj2 = { a: 1, b: 2 };
var obj3 = { a: 2, c: 3 };
var newObj = Object.assign(obj1, obj2,obj3);

console.log(obj1);      // {a: 2, b: 2, c: 3}
console.log(obj2);      // {a: 1, b: 2}
console.log(obj3);      // {a: 2, c: 3}
console.log(newObj);    // {a: 2, b: 2, c: 3}
  • 如果目标对象中具有相同的属性名称,则后面的源对象的属性将类似地覆盖前面的源对象的属性;
  • 该方法实现的是浅拷贝,继承属性和不可枚举属性是不能复制的;
4.2 Object.create() 创建一个新对象

  语法:Object.create(proto, {property})
  作用:创建一个新对象,使用现有的对象来提供新创建的对象的原型。
  实例:

var obj = Object.create(Object.prototype, {
	a: {
		writable: false, // 设置值是否可更改
		configurable: true, // 设置属性是否可配置
		enumerable: true, // 设置属性是否可枚举
		value: 1  // 值
	},
	b:{
		
	}
})
obj.a = 2;
console.log(obj);	// { a : 1}
4.3 Object.defineProperty() 定义或修改对象属性

  语法:Object.defineProperty(obj, key, descriptor)
  作用:在一个对象上定义新的属性或修改现有属性,并返回该对象。
  实例:

	var obj = { a : 1 };
	Object.defineProperty(obj, 'b',{
		configurable : true ,
		enumerable : true , 
		writable: true , 
		get: function(){}, 
		set: function(){}, 
		value : 2 
	})
4.4 Object.defineProperties() 定义或修改对象属性

  语法:Object.defineProperties(obj, props)
  作用:在一个对象上定义新的属性或修改现有属性,并返回该对象。
  实例:

var obj = { a: 1 };
Object.defineProperties(obj, {
    a: {
        value: 2,
        writable: false
    },
    b: {
        value: 3,
        writable: true
    }
});
obj.a = 4 ;
obj.b = 5 ;
console.log(obj);	// { a : 2 , b : 5 }
4.5 Object.getOwnPropertyDescriptor()

  语法:Object.getOwnPropertyDescriptor(obj, key)
  作用:返回对象中属性对应的属性描述。
  实例:

var obj = { a: 1 };
var desc = Object.getOwnPropertyDescriptor(obj, "a");
console.log(desc);	// {value: 1, writable: true, enumerable: true, configurable: true}
4.6 Object.getOwnPropertyNames()

  语法:Object.getOwnPropertyNames(obj)
  作用:返回一个包含对象中所有属性的数组。
  实例:

var obj = Object.create(Object, {
	a: {
		value: 1,
		enumerable: false
	},
	b: {
		value: 2,
		enumerable: true
	}
})
var keys = Object.getOwnPropertyNames(obj);
console.log(keys);      // ["a", "b"]
4.7 Object.keys()

  语法:Object.keys(obj)
  作用:返回一个包含对象中所有可枚举属性的数组。
  实例:

var obj = Object.create(Object, {
	a: {
		value: 1,
		enumerable: false
	},
	b: {
		value: 2,
		enumerable: true
	}
})
var keys = Object.keys(obj);
console.log(keys);      // ["b"]
4.8 Object.hasOwnProperty()

  语法:Object.hasOwnProperty(key)
  作用:检测对象中是否含有指定属性。
  实例:

var obj = { a : 1 }
obj.hasOwnProperty("a");		// true 
obj.hasOwnProperty("b");		// false
4.9 Object.freeze()

  语法:Object.freeze(obj)
  作用:不允许对对象进行任何修改。
  实例:

var obj = { a : 1 }
Object.freeze(obj);

更多关于 Object 的方法及属性,请 点击这里查看

三、 getter 和 setter

  对象的每一个属性都可以看成是由键值对构成的,我们可以使用 gettersetter 方法来代替属性值。通过这种方法定义的属性被称为 存取器属性

var obj = {
	_hour_: 0,
	get hour() {
		return "现在是" + this._hour_ + "点";
	},
	set hour(h) {
		this._hour_ = h < 10 ? '0' + h : '' + h;
	}
}

obj.hour = 22;
console.log(obj.hour);      // 现在是22点

obj.hour = 9;
console.log(obj.hour);      // 现在是09点

  当我们访问对象的属性时,会调用 getter 方法,给属性赋值时,会调用 setter 方法。
  使用 gettersetter 可以在对象的赋值和读取前做一些预处理的工作,比如上方代码在读取和设置时间时对其进行了一些预处理,保证在使用时不需要在进行额外的处理。

  当一个属性只存在 getter 方法时,这个属性就是只读属性,不允许对它的值进行修改;如果只存在 setter方法,则被称为只写属性,读取属性时会返回 undefined

四、 原型及原型链

  JS 本身并不具有 “类” 的概念,所有的一切都是对象。对象与对象之间的关系是如何联系起来的呢?就是靠着原型链串联在一起的。
  每一个对象都具有一个 __proto__ 属性,它指向的就是这个对象所继承的原型。而原型也拥有一个 prototype 属性与之相对应,也就是说:当前对象的 __proto__ 属性与它继承的原型对象的 prototype 相同。

var str1 = "字符串";
console.log(str1);
console.log(str1.__proto__);

var str2 = new String("字符串");
console.log(str2);
console.log(str2.__proto__);

console.log(str1.__proto__  === String.prototype);		

打印结果
  可以发现,我们通过直接赋值的方式创建的是一个普通的字符串类型的数据,而通过构造函数创建的则是一个对象类型的字符串数据,但他们的原型都指向了 String 对象。也就是说,他们都是从 String 这个 “父类” 下的 “子类” ,继承了父类的方法。
  接下来我们在打印一下 String 的原型和 Object 的原型:

console.log(str1.__proto__.__proto__);
console.log(Object.prototype);
console.log(str1.__proto__.__proto__ === Object.prototype);

打印结果
  这样的结果已经很明显了,我们声明的普通字符串继承自 String 对象,而 Striing 对象又继承了 Object 对象。这里的指向继承关系,我们就可以将其看做是 JS 的原型链。

  JS 的一切都是基于对象进行的设计,要说的内容也太多了点,洋洋洒洒写了半天感觉连个大概也没说明白,内置方法更是一带而过,原型和原型链也只是说了个大概,还有对象的继承等等根本就没有提。这里先立个 flag ,等写完函数的相关内容之后,再来重新写一下对象。(如果没实现的话,我就返回来把这段话删掉。笑)
在这里插入图片描述


种一棵树,最好的时间是十年前,其次是现在。人的一生,总的来说就是不断学习的一生。
蚕吐丝,蜂酿蜜。人不学,不如物。与其纠结学不学,学了有没有用,不如学了再说。


每篇文章纯属个人经验观点,如有错误疏漏欢迎指正。转载请附带作者信息及出处。您的评论和关注是我更新的动力!
请大家关注我的微信公众号,我会定期更新前端的相关技术文章,欢迎大家前来讨论学习。
从零开始学前端 - 老王的前端分享
都看到这里了,三连一下呗~~~。点个收藏,少个 Bug 。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值