面向对象就是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没有原型对象,不继承任何属性
案列:继承方法
![](https://i-blog.csdnimg.cn/blog_migrate/5f447e331a0f4bf56242b8c50a5d7f51.png)
<!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_ _=新对象,不推荐这种方式
![](https://i-blog.csdnimg.cn/blog_migrate/c7febc7f4ff06fa2725d6c2ad5b27ee1.png)
<!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禁止访问遍历
![](https://i-blog.csdnimg.cn/blog_migrate/dcf0e8abf8304cdbde40e65731bb9ed9.png)
<!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>
案列:保护对象禁止修改多个值
![](https://i-blog.csdnimg.cn/blog_migrate/9856896535ee719bdeff665a04fc5a71.png)
<!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>