专题 | js对象

面向对象就是js对象

面向对象概念

面向对象:将现实中一个事物的属性和功能,集中保存在程序中一个对象结构里。

面向对象三大特点:封装、继承、多态

封装

创建一个对象结构,集中保存一个事物的属性和功能 { }

便于大量数据的管理和使用

今后只要采用面向对象的方式开发,都要先封装一批对象,备用

对象

对象是javascript的基础,在javascript中一共有六种语言类型:string number boolean null undefined object

存储在对象的值,其实他们并没有真的放在对象中,而是通过引用指向真正存储值得位置。

javascript中除了字符串 数字 true false null undefined之外,其他值都是对象

javascript具有自有属性,还可以从一个称为原型对象继承属性。对象的方法通常是继承的属性。这种原型式继承是javascript的核心特征。

javascript中还有一些对象子类型,通常被称为内置对象。String Number Boolean Object Function Array Date RegExp Error,也叫内置函数,这些内置函数可以当做构造函数

 原型:每一个javascript对象(null除外)都和另一个对象有关联。另一个对象就是我们熟知的原型,每一个对象都从原型继承属性。

通过new Array()创建的对象原型就是Array.prototype

对象的结构

内置对象是指由ECMAScript规范定义的对象或类。数字 函数 日期 正则表达式.......

宿主对象 javascript解释器嵌入的宿主环境定义的。宿主对象也可以当做内置对象。

自定义对象:由运行中的javascript代码创建的对象

自有属性:直接在对象中定义的属性

继承属性:在对象的原型对象中定义的属性

检测对象属性

in

hasOwnpreperty 检测是否是自有属性

propertylsEnumerable()  检测自由属性和可枚举

!==

枚举函数

 Object.Keys()

Object.getOwnProperty-Names()

创建对象

对象字面量创建

   var 对象名={

    属性名:值,

     ........:........

   方法名:function(){

   }

}

访问属性:对象.属性名=值;

调用方法 对象.方法名(实参值)

 当属性名有空格,是连字符,保留字时,必须用字符串括起来,也就是加上双引号

如果在一个重复调用的函数中的循环体内使用了这种表达式,它将创建很多新对象,并且每次创建的对象的属性值也不同

对象字面量是一个表达式,这个表达式的每次运算都创建并初始化了一个新的对象。每次计算对象字面量时,都会计算他的每个属性的值

对象字面量创建的对象都具有同一个原型对象,并可以通过javascript代码object.prototype获得对原型对象的引用。

案列:字面量创建对象

 

 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		var people={
			name:"Kevin",
			age:25,
			hobby:"",
			breakfast:"cd_rf",
			intr:function(){
				console.log(`我叫${this.name},今年${this.age}岁了`)
			}
		}
		console.log(people);
		people.intr()
		</script>
	</body>
</html>

构造函数 new创建

var 对象名=new Object();

对象名.属性名=值

 对象名.方法名=function(){.....}

通过new Object( )创建的对象继承自Object.prototype

通过new 关键词和构造函数调用创建的对象的原型就是构造函数的prototype属性的值

案列:new创建对象

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		//new创建对象
		var people=new Object();
		people.name="Jason";
		people.age=18;
		people.intr=function(){
			return console.log(`我叫${this.name},我${this.age}岁了`)
		}
		console.log(people);
		people.intr();
		</script>
	</body>
</html>

字面量构造函数创建对象区别

字面量和构造函数添加对象的区别是一次添加多个还是逐个添加

这种方式揭露了对象底层也是关联数组

无论数组还是对象,本质都是键值对的集合

无论访问数组中的元素,还是访问对象中的属性,都可以用:

标准:数组/对象["属性名"]

 简写:数组/对象.属性名

            只不过,下标是数字,只能简写为[下标]

访问对象或数组中不存在的成员,不会报错,而是返回undefined

查找对象不存在,会报错

    固定套路:判断一个对象或数组中是否包含某个成员

    数组/对象.成员名!==undefined 说明包含该成员

    反之,如果===undefined说明不包含该成员

给对象或数组中不存在的成员强行赋值,不会报错,而是自动在该位置添加一个新成员

 固定套路:想给数组或对象中添加一个新成员。没有专门的函数的,只能野蛮的强行赋值!

 数组/对象.新成员名=值

for in 专门用来遍历关联数组,所以对象数组都可以用for in 来遍历。

    for(var 变量 in 数组/对象){

   

      //变量会依次接住数组或对象中每个属性名

      //可以用数组或对象[变量]方式,访问每个属性的值

       }

案列:for in

     

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		var people={
			id:1,
			name:"Kevin",
			salary:10000,
		}

		//for in循环
		for(var k in people){
			console.log(k+"----");
			console.log(people[k]);
		}
		</script>
	</body>
</html>

函数、方法的区别

   本质都是function(){}

   如果一个不属于任何对象的可独立使用的function,就称为函数

   如果包含在对象内,必须用对象。方式访问的function,就称为方法

案例:函数方法区别

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
	   //函数
	   function student(){
		   console.log("我是一个学生");
	   }
	   student();
	   
	   //方法
	   var people={
		   name:"Kevin",
		   age:17,
		   intr:function(){
			   console.log("我是Kevin,今年17岁了");
		   }
	   }
	   people.intr();
		</script>
	</body>
</html>

  克隆对象

     创建一个新的空对象,再把旧对象的每个属性赋值过去,再赋给新对象,判断新对象和旧对象地址是否相等

 案列:克隆对象

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		var Lisa={
			name:"Lisa",
			age:18
		}
		//克隆对象
		function clone(oldObj){
			//创建新对象,等待复制
			var newObj={};
			//遍历旧对象中的属性
			for(var key in oldObj){
				//取出旧对象中的每个属性
				var oldValue=oldObj[key];
				//添加到新对象中
				newObj[key]=oldValue;
			}
			return newObj;
		}
		var Lisa2=clone(Lisa);
		console.log(Lisa2);
		
		//判断两者是否相等,地址不相同说明复制成功
		console.log(Lisa==Lisa2);
		</script>
	</body>
</html>

     

用构造函数创建结构相同的对象

 定义构造函数,描述一类对象的统一结构

function 类型名(形参1,形参2...){

    this.新属性名=形参1;

    this.新属性名=形参2;

    this.新方法名=function(){.....}

}

var 对象名=new 类型名(属性值1,属性值2....) //调用构造函数,反复创建多个相同结构的对象

案例:函数结构相同对象

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		//创建学生的统一结构
		function Student(name,age){
			this.name=name;
			this.age=age;
			this.intr=function(){
				return console.log(`我叫${this.name},我${this,age}岁了`)
			}
		}
		//创建对象
		var Kevin=new Student("Kevin",16);
		var Julian=new Student("Julian",18);
		
		console.log(Kevin);
		Kevin.intr()
		console.log(Julian);
		Julian.intr()
		</script>
	</body>
</html>

继承--prototype

 为了节约内存,调用构造函数对象的同一个方法,就是继承

构造函数自带的原型对象prototype

object.prototype没有原型对象,不继承任何属性 

案列:继承方法 

继承肯定是继承已经有的

  

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		//创建学生的统一结构
		function Student(name,age){
			this.name=name;
			this.age=age;
			this.intr=function(){
				return console.log(`我叫${this.name},我${this,age}岁了`)
			}
		}
		//创建对象
		var Kevin=new Student("Kevin",16);
		var Julian=new Student("Julian",18);
		
		console.log(Kevin);
		Kevin.intr()
		console.log(Julian);
		Julian.intr()
		
		//继承
		function Student2(sname,sage){
			this.sname=sname;
			this.sage=sage;
		}
		//构造函数自带的原型对象
		Student2.prototype.intr=function(){
			return console.log(`我叫${this.sname},我${this.sage}岁了`)
		}
		
		//继承新建对象
		var Alan=new Student2("Alan",17);
		var Jason=new Student2("Jason",15);
		
		console.log(Alan);
		Alan.intr();
		console.log(Jason);
		Jason.intr();
		</script>
	</body>
</html>

Class---封装

封装:创建一个对象结构,集中保存一个事物的属性和功能 { }

          便于大量数据的管理和使用

          今后只要采用面向对象的方式开发,都要先封装一批对象,备用

继承没有达到封装的要求,于是有了class

创建一种类型,用class写

先写一个class  对象名{},再在{}里写构造函数,把构造函数的function和函数名改为constructor,方法直接写方法名

class 对象名{

       constructor(形参1,形参2....){

         .........

       }

    方法名(){

        ...........

     }

}

 案列:class创建对象

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		//class创建对象结构
		class Student{
			constructor(name,age) {
				this.name=name;
				this.age=age; 
			}
			intr(){
				return console.log(`我叫${this.name},我${this.age}岁了`)
			}
		}
	  //创建对象
	  var Kevin=new Student("Kevin",17);
	  var Alan=new Student("Alan",18);
	  console.log(Kevin);
	  Kevin.intr();
	  console.log(Alan);
	  Alan.intr();
		</script>
	</body>
</html>

class继承

多个类型之中包含部分相同的属性结果和方法定义

子类型继承父类型

class 子类型 extends 父类型{...}

子类型请求父类型

super ()代表父类型的构造函数

案列:class继承案列

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
	   //父类型定义子类型都有的属性方法
	   class Enemy{
		   constructor(x,y) {
		       this.x=x;
			   this.y=y;
		   }
		   fly(){
			   console.log(`飞到x=${this.x},y=${this.y}位置`);
		   }
	   }
	   
	   //子类型plane  继承extends父类型Enemy
	   class plane extends Enemy{
		   constructor(x,y,score) {
		       //子类型请求super父类型
			   super(x,y);
			   this.score=score;
		   }
		   getScore(){
			   console.log(`击落敌机,得${this.score}分`);
		   }
	   }
	   
	  var Kevin=new plane(50,100,5);
	  console.log(Kevin);
	  Kevin.fly();
	  Kevin.getScore();
	  
	  //子类型shan 继承extends父类型Enemy
	  class shan extends Enemy{
	  		   constructor(x,y,award) {
	  		       //子类型请求super父类型
	  			   super(x,y);
	  			   this.award=award;
	  		   }
	  		   getAward(){
	  			   console.log(`奖励${this.award}分`);
	  		   }
	  }
	  
	  var Jason=new shan(60,120,'生命值+30');
	  console.log(Jason);
	  Jason.fly();
	  Jason.getAward();
		</script>
	</body>
</html>

自有属性 共有属性

      自有属性:保存在子对象内,只归子对象独有的属性

      共有属性:保存在原型对象中,归所有子对象共有的属性

 获取属性值  自有属性和共有属性无差别,

                     访问方式都是:“子对象.属性名”

                     访问原理:现在子对象内中查找自有属性,找不到就沿着--proto--去父对象中找

修改属性值

                   修改自有属性值  子对象.属性名=新值

                   修改共有属性值  构造函数名.prototype.共有属性(方法名)=新值

 案例:访问获取自有属性和共有属性

    

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		function Student(name,age){
			this.name=name;
			this.age=age;
		}
		Student.prototype.className="初一二班";
		var Kevin=new Student("Kevin",18);
		var Alan=new Student("Alan",16);
		
		//访问自有属性
		console.log(Kevin.name,Kevin.age);
		console.log(Alan.name,Alan.age);
		
		//访问共有属性
		console.log(Kevin.className,Alan.className);
		</script>
	</body>
</html>

 案例:修改自有属性和共有属性

修改共有属性时,有些人会写成 子对象.共有属性=新值,这种方式会造成子对象生成了新的自有属性

之后子对象会优先使用自有属性,不会使用共有属性

   

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		function Student(name,age){
			this.name=name;
			this.age=age;
		}
		Student.prototype.className="初一二班";
		var Kevin=new Student("Kevin",18);
		var Alan=new Student("Alan",16);
		
		//修改自有属性
		var Kevin=new Student("Kevin",13);
		var Alan=new Student("Jason",13);
		console.log(Kevin.name,Kevin.age);
		console.log(Alan.name,Alan.age);
		
		//正确修改共有属性
		Student.prototype.className="初一四班";
		console.log(Kevin.className,Alan.className);
		
		//错误修改共有属性
		Alan.className="初一五班";
		console.log(Kevin.className,Alan.className);
		</script>
	</body>
</html>


自定义函数添加到数组原型对象中

任何对象都有__pro__属性

Array.prototype.函数名=function(..){

//目标

}

子对象.函数名()//调用自定义方法

案列:数组添加函数求和

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		//在数组上自定义一个求和函数
		Array.prototype.sum=function(){
			//this指将来调用sum函数前的某个子对象,使用this是为了方便适应各种情况
			var result=0;
			for(var i=0;i<this.length;i++){
				result+=this[i]
			}
			return result;
		}
		
		//求和
		var arr1=[1,10,46,78];
		console.log(arr1.sum());
		
		var arr2=[2,3,6];
		console.log(arr2.sum());
		</script>
	</body>
</html>

原型链

 由多级父对象,逐级继承,形成的链式结构

保存着一个对象可用的所有属性和方法

成员的使用顺序,就近原则,先用自己的,再用共有的

原型链就是 对象先在自己里找是否有这个属性,如果没有,就问自己的原型对象有吗,自己的原型对象没有,自己的原型对象会问自己的原型对象,直到层层递进的原型对象被问完,没有了

但这种原型链只有在查询属性时才会存在,在设置属性时不会有继承问题

原型链与作用域链的区别

作用域链保存是变量,不带点的变量,无法进入对象里查找

原型链:保存的是对象的属性和方法。带点的属性和方法,在当前对象的原型链范围内查找

多态 override 重写

多态:一个函数,在不同的情况下,表现不同的状态。

案例:不同的东西调用相同的函数,结果不同

不同的子对象,调用相同的函数,输出的结果的格式和内容不同

数组的原型对象和日期的原型对象,都为了各自不同的目的,重新定义了toString()函数。不同类型原型对象中的toString()函数,输出的内容格式不同!

所有不同类型的子对象,调用toString()时,其访问的不是爷爷的toString(),而是当前类型的原型对象中定义个toSring()--重写--多态。

 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		var Kevin={
			name:"Kevin",
			age:20
		}
		//创建数组和日期
		var arr=[1,2,3];
		
		var now=new Date();
		
		//对象调用函数toString
		console.log(Kevin.toString());
		//数组调用函数toString
		console.log(arr.toString());
		//日期调用函数toString
		console.log(now.toString());
		</script>
	</body>
</html>

重载overload

一个函数,传入不同的实参值,执行不同的操作。(之前学了)

重写override

在一个子对象中,又重新定义了一个和父对象中成员同名的自有成员。

重写原因:从父对象继承来的成员不一定好用,比如对象的toString()值

                 只要在子对象中定义一个新成员,成员名和父对象中不好用的成员同名即可!之后,子对象会优先使用自己重写的自有成员。父对象的成员被覆盖/重写

   案列:重写案列

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		function Student(name,age){
			this.name=name;
			this.age=age;
		}
		
		var Kevin=new Student("Kevin",18);
		var Alan=new Student("Alan",20);
		
		//重写属性前
		console.log(Kevin.toString());
		console.log(Alan.toString());
		
		//重写属性toString
		Student.prototype.toString=function(){
			return `学生姓名${this.name},学生年龄${this.age}`
		}
		
		//重写属性后
		console.log(Kevin.toString());
		console.log(Alan.toString());
		</script>
	</body>
</html>

自定义继承

只更新一个子对象的父对象,其实就是修改子对象的__proto_ _属性,指向新的父对象

proro方式---自定义继承--不推荐

就是单独给某一个创建好的对象添加新的信息

子对象_ _proto_ _=新对象,不推荐这种方式

原本的kevin好像也受到了修改后proto的影响,所以用了其他的来做对比

       

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		//正常的
		function Student(name,age){
			this.name=name;
			this.age=age;
		}
	    var Kevin=new Student("Kevin",18);
		var Alan=new Student("Alan",20);
		console.log(Kevin);
		console.log(Alan);
		
		//继承添加的对象
		var father={
			money:10000,
			car:"大众"
		}
		//给子对象Kevin添加father
		Kevin._proto_=father;
		console.log(Kevin);
		</script>
	</body>
</html>

Object.setPrototypeOf(子对象,父对象)--自定义继承

就是单独给某一个创建好的对象添加新的信息

案列:Object.setPrototypeOf(子对象,父对象)自定义继承

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		//正常的
		function Student(name,age){
			this.name=name;
			this.age=age;
		}
	    var Kevin=new Student("Kevin",18);
		var Alan=new Student("Alan",20);
		console.log(Kevin);
		console.log(Alan);
		
		//继承的对象
		var father={
			money:10000,
			car:"大众"
		}
		//给子对象Kevin添加father
		Object.setPrototypeOf(Kevin,father)
		console.log(Kevin);
		</script>
	</body>
</html>

构造函数.prototype=新父对象---自定义继承

更换多个子对象的父对象,就是在更换构造函数的原型对象,但要在创建子对象前。

通过new 关键词和构造函数调用创建的对象的原型就是构造函数的prototype属性的值 

案列:更换多个子对象的父对象

·

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		//最开始的模样
		function Student(name,age){
			this.name=name;
			this.age=age;
		}
	   
		//继承的对象
		var father={
			money:10000,
			car:"大众"
		}
		//给多个子对象更换父对象
		Student.prototype=father;
		
		var Kevin=new Student("Kevin",18);
		var Alan=new Student("Alan",20);
		console.log(Kevin);
		console.log(Alan);
		</script>
	</body>
</html>

保护对象

防止修改对象属性值和结构

保护对象禁止修改单个值

Object.defineProperty(对象名,“属性名”,{

开关名:true/false

})//用函数Object.defineProperty来控制这几个值,禁止修改单个值

对象属性有几个值

value 存储属性值

writable 控制是否修改属性值,默认为true,true可以修改

enumerable 控制是否可以被for in 遍历

configurable 控制是否可以删除属性和修改前两个开关的状态

                    并且configurable一旦关闭,再改为true则无效了,还是保持false状态

保护对象禁止修改多个值

同时修改一个对象的多个属性的开关,用Object.defineProperties(对象名,{

      属性名:{ 

     开关名:true/false;

  },

    属性名:{ 

     开关名:true/false;

  }

.......

})

 

案列:对象很容易被修改,访问

删除属性 delete,只能删除自有属性,不能删除继承属性,继承属性的删除要从原型对象上删

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		var people={
			id:1,
			name:"Kevin",
			salary:10000
		}
		console.log(people);
		
		//修改对象id
		people.id=6;
		//删除姓名
	    delete people.name;
		console.log(people)
		
		//遍历员工属性
		for(var s in people){
			console.log(people[s]);
		}
		</script>
	</body>
</html>

 

案列:writable禁止修改单个属性

 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		var people={
			id:1,
			name:"Kevin",
			salary:10000
		}
		
		//writable禁止修改单个属性
		Object.defineProperty(people,"id",{
			writable:false
		})
		//修改id
		people.id=10;
		console.log(people);//修改失败
		</script>
	</body>
</html>

案列:enumerable禁止访问遍历

属性salary无法访问

 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		var people={
			id:1,
			name:"Kevin",
			salary:10000
		}
		
		//enumerable禁止访问单个属性
		Object.defineProperty(people,"salary",{
			enumerable:false
		})
		//循环
		for(var s in people){
			console.log(people[s]);//salary循环失败
			}
		</script>
	</body>
</html>

案列:configurable禁止删除单个属性值

 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		var people={
			id:1,
			name:"Kevin",
			salary:10000
		}
		
		//configurable禁止删除单个属性
		Object.defineProperty(people,"name",{
			configurable:false
		})
		//删除name
	    delete people.name;
		console.log(people);//删除失败
			
		</script>
	</body>
</html>

案列:保护对象禁止修改多个值

例子只做了salary,所有只有salary无法参与循环

 

 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		var people={
			id:1,
			name:"Kevin",
			salary:10000
		}
		
		//禁止修改访问多个值
		Object.defineProperties(people,{
			id:{
				writable:false,
				configurable:false
			},
			name:{
				configurable:false
			},
			salary:{
				enumerable:false,
				configurable:false
			}
		})
			
			//尝试修改访问属性
			people.id=10;
			delete people.name;
			for(var s in people){
				console.log(people[s]);
			}
			
			console.log(people);
		</script>
	</body>
</html>

访问器属性

不实际存储属性值,仅提供对另一个数据属性的保护,当需要自定义规则来保护属性时,用访问器属性

1.将实际保存数据的属性,隐形埋名,半隐藏

Object.defineProperty(对象,“_属性名”,{

    value:属性值,

    writable:true,

   enumerable:false,

   configurable:false

})

2.将原属性变成一个访问器属性替身,在替身中定义两个保镖函数:Object.defineProperty(对象,"原属性名",{

      get:function(){

    return this._属性名

   },

  set:function(value){

      if(value符合条件){

     this._属性名=value

},

enumerable:true,

configurable:false

}

})

注意:

获取访问器属性,内部自动调用get()

修改访问器属性,内部自动调用set()

案列:修改对象的某个属性值

 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		var people={
			id:1,
			name:"Kevin",
			age:25,
			salary:10000
		}
		
		//将年龄修改到18-65之间
		Object.defineProperty(people,"_age",{
			//value 将旧属性的属性值,转移到这个半隐藏的新属性中保存
			value:people.age,
			writable:true,
			enumerable:false,//半隐藏
			configurable:false
		})
		
		//将旧属性变成替身+保膘的结构
		Object.defineProperty(people,"age",{
			//get 从受保护的属性中取出现在的属性值
			get:function(){
				return this._age;//_age正版
			},
			//set 负责接受外界传入的现在,经过验证后,保存到受保护的属性中
			set:function(value){
				//如果满足条件,就保存,否则报错
				if(value>=18&&value<=65){
					this._age=value;
				}else{
					throw Error("年龄超出范围,请重新输入");
				}
			},
			enumerable:true,//替受保护的属性抛头露面
			configurable:false
		})
		//验证语法是否正确
		people.age=28;
		console.log(people);
		
		people.age=17;
		console.log(people);
		</script>
	</body>
</html>

保护对象结构

禁止添加属性

Object.preventExtensions(对象)

 案列:禁止添加属性

 

 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		var people={
			name:"Kevin",
			age:25,
			salary:10000
		}
		
		//现在属性能够任意添加
		people.hobby="读书";
		console.log(people);
		
		//阻止添加属性
		Object.preventExtensions(people);
	    people.breakfast="饺子,煎鸡蛋";
		console.log(people);
		</script>
	</body>
</html>

密封  Object.seal

 Object.seal(对象);

不能添加新属性,不能删除已有属性,但是属性值可以修改

原理:自动调用Object.preventExtensions()防扩展

           自动设置每个属性的configurable:false,禁止删除每个属性

 案列:密封seal

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		var people={
			name:"Kevin",
			age:25,
			salary:10000
		}
		
		//密封seal
		Object.seal(people);
		
		//尝试对对象数据进行修改
		people.breakfast="饺子,煎鸡蛋";
		people.age=28;
		delete people.salary;
		
		console.log(people);
		</script>
	</body>
</html>

冻结Object.freeze

Object.freeze(对象)

不能删除属性,添加属性,修改属性值

原理:自动调用Object.preventExtensions()防扩展

           自动设置每个属性的configurable:false,禁止删除每个属性

           自动设置每个属性的writable:false

案列:冻结freeze

 

 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		var people={
			name:"Kevin",
			age:25,
			salary:10000
		}
		
		//冻结freeze
		Object.freeze(people);
		
		//尝试对对象数据进行修改
		people.breakfast="饺子,煎鸡蛋";
		people.age=28;
		delete people.salary;
		
		console.log(people);
		</script>
	</body>
</html>

 Object.create()

如果没有构造函数,也想创建子对象,继承父对象-----案列1

创建子对象继承父对象,又为子对象添加自有属性------案列2

 

var 新对象=Object.create(父对象,{

自有属性:{ //格式必须和defineProperties格式一致

     value:属性值,

     开关:true或false,

    .....:....

}}

)

案列1:create

如果没有构造函数,也想创建子对象,继承父对象

 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		var people={
			name:"Kevin",
			age:25,
			salary:10000
		}
		
		
		//创建了一个新的空对象,让新对象继承指定的父对象
		var Alan=Object.create(people);
		console.log(Alan);//{}
		console.log(Alan.name,Alan.age,Alan.salary);//父对象的值
		</script>
	</body>
</html>

 案列2:create

创建子对象继承父对象,又为子对象添加自有属性

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		var people={
			name:"Kevin",
			age:25,
			salary:10000
		}
		
		//创建新对象,新对象指定父对象,为新对象添加自有属性
		var Jason=Object.create(people,{
			breakfast:{
				value:"饺子,煎蛋",
				writable:true,
				enumerable:true,
				configurable:false
			}
		});
		console.log(Jason);
		console.log(Jason.name,Jason.age,Jason.salary);
		</script>
	</body>
</html>

 

this指向

this在运行时是根据调用的位置动态绑定的

 对象方法里this指对象名

      为了让结果是动态变化的,把console里的值用变量代替,但是对象里的属性使用,需要对象首肯,所以要加对象名,这样写死了对象名.属性名。但是在开发中修改名字很常见,这种方式也叫紧耦合,容易出错。所以在内部用this替代对象名。
 


 

 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		var people={
			name:"Kevin",
			age:25,
			intr(){
				//console.log(`我叫${people.name},今年${people.age}岁了`)
				console.log(`我叫${this.name},今年${this.age}岁了`)
			}
		}
		people.intr();
		</script>
	</body>
</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值