js对象基础小结

一、对象的定义

js的数据类型基本分为两大类:基本数据类型和复杂的数据类型。基本的数据类型有String,Number,Boolean,Undefined,Null;复杂的数据类型(引用数据类型)主要是对象Object。对象是可以使用属性值去访问对象的值。对象是属性的无序集合

二、对象的创建

1.直接量创建/字面创建

创建时已经知道对象的属性和方法,直接用花括号定义,同时列出属性。(创建一个单独的对象)

// 定义对象
var obj = {
	name: 'joy',//定义对象属性
	type: 'people',
	click: function(){
		console.log(this.name + '你好'); // 定义对象方法
	}
}
// 对象可以直接输出
// 属性和方法可以直接调用
obj.click(); //joy你好

2.使用关键字new创建

创建对象时还不知道对象的属性和方法,后续动态添加。使用js内置的对象Object和关键字new进行创建。(创建一个单独的对象)
(1)js默认的对象(内置对象)
window,环境对象
String,字符串
Number ,数值
Boolean,布尔
Array,数组 数据的有序排列方式
Date,时间对象
Error ,错误
Function ,函数
Object,对象
RegExp,正则对象

(2)new关键字创建

// 定义对象
var obj = new Object();
obj.name = "joy"; //添加对象的属性
obj.click = function(){ //添加对象的方法
	console.log(this.name+"你好");
}
console.log(obj.name);// "joy"
obj.click(); //joy你好

3.使用构造函数创建对象

创建相同结果的对象,批量创建对象时,使用构造函数创建。
(1)第一步是定义构造函数(统一的结构)
为了与普通的函数进行区分,采用首写的大写字母的驼峰法进行定义,普通函数使用首写的小写字母的驼峰法进行定义。

// 定义构造函数
function PeopleModel(value1){//传入属性参数值
	this.name = value1;
	this.createPeople = function(){
		console.log("创建人,名字叫"+ this.name);
	}
}

(2)使用new调用构造函数创建对象

// 利用构造函数,创建对象
var obj1 = new PeopleModel('joy');
console.log(obj1.name); // joy
obj1.createPeople();// 创建人,名字叫joy
var obj2 = new PeopleModel('zyh');
console.log(obj2.name); // zyh
obj2.createPeople(); // 创建人,名字叫zyh

4.关键字new

构造函数创建时用new关键字,才会有返回值,返回一个对象。如果不用new关键字去调用构造函数的话,会被当成普通函数去处理,没有返回是,返回undefined。
使用new关键字创建的对象的原理,实际是在对象里面私下进行一系列操作,首先进去会var this = Object.create(PeopleModel(构造函数名字).prototype),用此方法创建了对象,此时this是一个已经创建好的空对象,缺少属性,添加好属性后,对象私自会return出 this这个对象,才是赋值给了哪个变量,哪个变量就会是this所指。
重点是
如果构造函数中 有return值出来,如果return出的是原始值,则不会破坏new 出来的对象,不破坏this。
如果构造函数有return值,如果return出来的是一个对象,则会破坏this

// 返回对象
function PeopleModel(value1){//传入属性参数值
	this.name = value1;
	this.createPeople = function(){
		console.log("创建人,名字叫"+ this.name);
	}
return {} // 返回对象
}
var obgj1 = new PeopleModel('joy');
console.log(obj1); // 此时没有返回我们预期的对象,会返回  {}
// 如果返回原始值
function PeopleModel(value1){//传入属性参数值
	this.name = value1;
	this.createPeople = function(){
		console.log("创建人,名字叫"+ this.name);
	}
return 2 // 返回原始值 数值
}
var obgj1 = new PeopleModel('joy');
console.log(obj1); // 此时没有返回我们预期的对象,会返回对象
// obj1 = {
//	name: 'joy',
//	createPeople: function(){
//		console.log("创建人,名字叫"+ this.name);
//	}
//}

三、对象的增删改查

1.增加

为对象增加属性或者方法。如果增加了属性没有赋值直接输出,会报undefined。
只是针对当前对象的属性进行操作,而不会影响到当前对象的原型的属性

var obj = {};
obj.name;
console.log(obj.name); //如果没有赋值,输出 undefined
obj.name = "joy";
console.log(obj.name);// "joy"

2.删除

删除对象的属性,使用delete方法。
只是针对当前对象的属性进行操作,而不会影响到当前对象的原型的属性

var obj = {
	name: "joy"
}; 
console.log(obj.name); // "joy"
delete obj.name; // true 删除对象属性,返回布尔值,删除是否成功
console.log(obj.name);// undefined

3.修改

直接通过赋值操作,重新赋予值就可以。
只是针对当前对象的属性进行操作,而不会影响到当前对象的原型(相当于新建函数的父)的属性

4.查找

查找方式对象给了两种方式方式。
查询是先看看当前对象本身是否设置了该属性,如果当前对象未设置该属性,则再看该对象的原型中是否设置了该属性,若两者都没有,则返回undefined

var obj = {
	name: "joy"
}; 
obj['name'] // 第一种
obj.name // 第二种

四、包装类

原始值有 number、string、boolean、null、undefined。null和undefined没有包装类。原始值不是对象,没有属性值。由于有包装类,所有可以使用属性。
但是包装类在每次执行完包装结束就会销毁掉。

五、原型

1.原型定义

原型是构造函数function对象的一个属性,定义了构造函数定义出的对象的公共祖先。原型我自己默认为父辈~新定义的对象可以继承原型的属性和方法,原型也是对象

2.原型作用

利用原型特点和概念,可以提取共有属性。将一类对象的共有属性提取出来,放到该类对象的原型中。可供继承和使用。

3.查看原型

每一个构造函数里面有一个隐藏的接口__proto__这个属性,连接着对象的原型。没有__proto__这个就谈不到对象的继承。

PeopleModel.prototype = { //原型
	play: function(){
		console.log("玩");
	}
}
function PeopleModel(name) { //构造函数  默认的私下操作
	var this = Object.create(PeopleModel.prototype);//创建空对象
	// 默认创建属性__proto__,存储了PeopleModel.prototype。
	//__proto__是对象key值,PeopleModel.prototype是value值
	this.name = name;
	return this;
}
// 对象的创建
var obj = new PeopleMode("joy");
console.log(obj.__proto__) //可以直接打印出来原型

4.查看构造函数

使用constructor去查看构造函数,constructor属性位于构造函数的原型中,其中存储的是构造函数信息。

function PeopleModel(name,age){
	this.name = name;
	this.age = age;
}
var person = new PeopleModel('joy','18');
person.constructor; // 打印输出构造函数
/*
function PeopleModel(name,age){
	this.name = name;
	this.age = age;
}
*/

六、原型链

1.原型链的组成

原型链决定了对象中公共属性和公共方法的继承和使用顺序。
原型链的最顶端是new Object()。

//原型链是: Child -> new Parent() -> new GrandParent() -> new Object()//顶端;
function GrandParent() {
	this.name = 'GrandParent';
    this.a = 3;
}

function Parent() {
	this.name = 'parent';
	this.b = 2;
}
Parent.prototype = new GrandParent();

function Child() {
	this.name = 'child';
	this.c = 1;
}
Child.prototype = new Parent();
//实例化一个对象
var child = new Child();
console.log(child); // Child {name: "child", c: 1}

//继承从而是如果找不到会继续向上去查找原型链上面的值
console.log(child.a); // 3  
console.log(child.b); //2
console.log(child.c); //1

有个特殊的知识点是关于查询构造函数的
新建对象.constructor的返回值问题

function GrandParent() {
	this.name = 'GrandParent';
    this.a = 3;
}
function Parent() {
	this.name = 'parent';
	this.b = 2;
}
//如果没有修改Parent的原型,此时实例化Parent对象,再去查询实例化对象的构造函数查询的是正确的。会按照我们想的来的。
var child = new Parent();
console.log(child.constructor); 
//function Parent() {
//	this.name = 'parent';
//  this.b = 2;
//}

//如果修改了Parent的原型,此时Parent的原型是祖级构造函数GrandParent实例的,此时作为实例化后的GrandParent()的原型里面的constructor属性是GrandParent构造函数,所以如果再去查找,会一直查到最顶级的那一层的修改原型的那一层。
Parent.prototype = new GrandParent();
var child = new Parent();
console.log(child.constructor); 
//function GrandParent() {
//	this.name = 'GrandParent';
//    this.a = 3;
//}

2.原型链上面的增删改查

原型链是: Child -> new Parent() -> new GrandParent() -> new Object()//顶端;
(1)增加
为child实例对象添加属性,总是添加为其自己本身的属性,对原型和原型链是没有影响的。
(2)删除
使用delete操作符只能删除child实例对象自己本身的属性,而无法删除由原型继承而来的属性
(3)修改
A.第一种
如果修改的属性为继承自原型的,且值类型为原始值,则仅仅修改的是该实例对象的属性,对原型无法造成影响。(复制一份原始值进行修改)

A.prototype = {
    has: 22 //原型里面是一个原始值
}
function A () {
	this.name = 'joy';
}
var a = new A();
var b = new A();
a.has = 66; //修改原始值
console.log(a.has); // 66  自己修改,改了自己的,没改原型的
console.log(b.has); // 22 

B.第二种
如果修改的属性为继承自原型的,且值类型为引用值(对象或者数组),会再次分不同的情况。
第一,如果是直接整体修改value值,整体替换,则不会影响原型

A.prototype = {
    has: [2,3] //原型里面是一个引用值,数组
}
function A () {
	this.name = 'joy';
}
var a = new A();
var b = new A();
a.has = 66; //修改   把数据整体替换  [2,3]->66
console.log(a.has); // 66  自己修改,改了自己的,没改原型的
console.log(b.has); // [2, 3] 

第二,如果是在原型里面修改value值中的某一个具体的值,就会影响原型

A.prototype = {
    has: [2,3] //原型里面是一个引用值,数组
}
function A () {
	this.name = 'joy';
}
var a = new A();
var b = new A();
a.has[0] = 66; //修改引用值中的具体某一个值
console.log(a.has); // [66, 3]  自己修改,改了自己的,同时修改了原型的
console.log(b.has); // [66, 3] 修改了原型的

(4)查找
查询是如果构造函数中有没有要查询的属性,若有,则直接返回,若没有则顺序在原型链上查询,若一直到原型链顶端后仍没有要查询的属性,则返回undefined。

七、命名空间(推荐的模块开发)

可以利用对象创建命名空间来管理变量,防止污染全局。开发更加整洁。

var obj = {
	people1: {
		name: "joy",
		age: "18"
	},
	people: {
		name: "zyh",
		age: "20",
	}
}
//这样name值可以放在不同的people命名空间下面,不会污染全局,可以通过中间值去访问到。

八、对象的枚举(包含属性的归属问题和是否属于对象)

1. obj.hasOwnProperty(‘prop’)

首先区分对象的自身属性和继承属性
自身属性是对象自己构造函数中的生成的或者是自己后来添加的。
继承属性是对象从原型中继承下来的属性。
obj.hasOwnProperty(‘prop’)就是判断该属性是从原型继承来的还是自身的

Person.prototype.age = 18; //定义原型
function Person () { //定义构造函数
	this.name = 'lyl';
}
var person = new Person(); //实例化对象
for(var key in person){
	console.log(person[key]); // 'ly1'  18  都打印出来了
}
//如果使用了hasOwnProperty(属性值)进行判断  就会只打印自己的属性
for(var key in person){
	if(person.hasOwnProperty(key)) {
		console.log(person[key]); // 'ly1'  只打印构造函数里面的  原型的不会打印出来的
	}
}

2. ‘prop’ in obj

属性是是否在对象中。
in操作符用来判断该对象obj上是否有该属性prop,prop既可以是自身属性,也可以是继承属性。
返回布尔值

Person.prototype.age = 18; //定义原型
function Person () { //定义构造函数
	this.name = 'lyl';
}
var person = new Person(); //实例化对象
console.log('age' in person); // true
console.log('name' in person); // true
delete person.name;
console.log('name' in person); //false

3. obj instanceof object

返回布尔值
用来判断obj实例对象是否为Object构造函数创建的。

Person.prototype.age = 18;
     function Person () {
         this.name = 'lyl';
     }
var person = new Person(); //实例化对象
console.log(person instanceof Person); // true
console.log(new Object() instanceof Person) // false

九、call() && apply() 强借

函数.call(要变化后的this指向,参数1,参数2…) 参数是列出来的传入的
函数.apply(要变化后的this指向,[参数1,参数2…]) 参数是数组形式传入的

function test() {
	console.log(this);
}
test(); // window全局对象
var demo = {
	show: function () {
		console.log(this);
	}
}
demo.show(); // demo = {}
test.call(demo);  // demo2 = {}

十、对象的克隆

对象的克隆分为深克隆和浅克隆。
浅克隆是克隆的和被克隆的对象在克隆操作完成后,指向同一个地址引用,改变其中一个,另一个也会改变,而深克隆则不会产生此现象。

//浅克隆
var demo = {
	name: 'joy',
	age: 18
}
console.log(demo);// {name: "joy", age: 18}
var c = demo;
demo.name = 'zyh'; //修改demo属性
console.log(demo);  // {name: "zyh", age: 18}
console.log(c); // {name: "zyh", age: 18} 也修改了
//深克隆
function deepClone(obj){
	var str,retObj = Object.prototype.toString.call(obj) === '[object Array]' ? [] : {}; 
// 使用Object.prototype.toString.call(obj)方法可以直接判断出传入值的类型。使用call是担心后面toString方法被重写了  所以从顶部借用。  此是创建一个空的对象,等待把属性值重新放进来,构成一个新的对象新的引用地址。
	if(typeof obj !== 'object'){
		return;
	}else if(window.JSON){
		str = JSON.stringfy(obj);
		retObj = JSON.parse(str);
	} else {
		for(var key in obj) {
			retObj[key] = typeof(obj[key]) == 'object' ? deepClone(obj[key]) : 		obj[key];
		}
	}
	return retObj;
}
var demo = {
	name: 'joy',
	age: 18
}
console.log(demo);// {name: "joy", age: 18}
var c = deepClone(demo);
demo.name = 'zyh'; //修改demo属性
console.log(demo);  // {name: "zyh", age: 18}
console.log(c); // {name: "joy", age: 18} 也修改了
  • 学习了别人的知识做的笔记,也添加补充了知识点,为了自己学习的时候方便看和复习,如有雷同,纯属巧遇,如有冒犯请联系本人修改。
  • 学习的博客地址为:https://www.cnblogs.com/libin-1/p/5911190.html

猜你喜欢

转载自blog.csdn.net/weixin_43970021/article/details/86480424
今日推荐