一.对象属性设置 -- defineProperty
1.Object.getOwnPropertyDescriptor() 获取对象属性
var Person={
name:"zs",
}
var des=Object.getOwnPropertyDescriptor(Person,"name")
console.log(des.value) //zs
console.log(des.configurable) //true
console.log(des.writable) //true
console.log(des.enumerable) //true 在对象里面直接定义都为true
2.****对象的数据属性
value 属性的属性值
configurable 能否删除属性的值
writable 能否修改属性的值
enumerable 能否遍历(枚举)属性的值
(0)var Person={}
Object.defineProperty(Person,"name",{value:"zs"})
var des=Object.getOwnPropertyDescriptor(Person,"name")
console.log(des.value) //zs
console.log(des.configurable) //false
console.log(des.writable) //false
console.log(des.enumerable) //false 对象为空时都为false
(1)writable 能否修改属性的值
Object.defineProperty(Person,"name",{value:"zs",writable:false})
console.log(Person.name) //zs
Person.name="ls" //修改失败
console.log(Person.name) //zs
(2)enumerable 能否遍历(枚举)属性的值
Object.defineProperty(Person,"name",{value:"zs",enumerable:false})
var v1=Object.keys(Person)
console.log(v1)
(3)configurable 能否删除属性的值
Object.defineProperty(Person,"age",{value:"21",configurable:true})
console.log(Person.age) //21
delete Person.age
console.log(Person.age) //undefined
3.对象的访问属性
get: 在读取属性时调用的函数
set: 在写入属性时调用的函数
var Person={"_name":"zs",age:23}
var v1=""
Object.defineProperty(Person,"name",
{get:function(){
// console.log("get...")
return this._name
},
set:function(val){
console.log("set...",val)
if(val=="ls"){
v1="He is "+val
this.age=55
}
}
})
// console.log(Person.name)
Person.name="ls"
console.log(v1);
console.log(Person.age);
4.vue MVVM 原理实现
<input type="text" id="unamea">
显示:<span id="show"></span>
<script>
var myobj={}
Object.defineProperty(myobj,'uname',{
set:function(val){
document.getElementById("show").innerText=val },
get:function(){
// return myobj.uname }
})
document.getElementById("unamea").addEventListener("keyup",function(event){
esrc=event.target
myobj.uname=esrc.value
})
二.继承
1.约定
(1)
function Person(){
var name="zs" //私有的基本属性
var friends=["ls","ww"] //私有的引用属性
function f1(){} //私有的函数
}
(2)
function Person(){
this.name="zs" //实例的基本属性
this.friends=["ls","ww"] //实例有的引用属性
this.f1=function(){} //实例的函数
}
(3)
function Person(){}
Person.prototype.name="zs" //原型的基本属性
Person.prototype.friends=["ls","ww"]//原型有的引用属性
Person.prototype.f1=function(){} //原型的函数
2.原型链继承
function Animal(){
this.name="animal"
this.frineds=[]
this.say=function(){console.log("say...");}
}
Animal.prototype.eat=function(){console.log("eat...");}
function Cat(){ //构造函数
this.name="cat00"
}
//继承
Cat.prototype=new Animal()
Cat.prototype.name="cat" //原型
//实例
var c1=new Cat()
c1.name="jfcat"
console.log(c1.name)
c1.say()
c1.frineds.push("jfcat01")
console.log(c1.frineds);
var c2=new Cat()
console.log(c2.name)
console.log(c2.frineds);
总结:
核心:Cat.prototype=new Animal()拿父类实例充当子类原型对象
原型链的查找顺序:实例-->实例对象的构造函数-->实例对象原型-->父类构造原型-->父类对象原型
优点:简单易于实现
缺点:原型的引用类型属性是所有实例共享的
创建子实例时无法向父类构造函数传参
3.原型链原理
function Animal(){}
Animal.prototype.name="animal"
Animal.prototype.say=function(){console.log("hello")}
console.log(Animal);
console.log(typeof Animal.prototype)
console.log(Animal.prototype.constructor)
(1)每个函数都有一个显示的"prototype"属性,该属性指向原型对象
(2)原型对象中的"constructor"属性,指向函数本身
function Cat(){}
Cat.prototype=new Animal()
// console.log(Cat)
// console.log(Cat.prototype)
// console.log(Cat.__proto__)
var c1=new Cat()
var c2=new Cat()
console.log(c1.__proto__==Cat.prototype)//true
console.log(Cat.prototype.__proto__==Animal.prototype);//true
console.log(Animal.prototype.__proto__==Object.prototype);//true
console.log(Object.prototype.__proto__==null);//true
(3)new创建的对象,没有prototype属性
function Animal(){}
Animal.prototype.name="animal"
Animal.prototype.say=function(){console.log("hello")}
function Cat(){}
Cat.prototype=new Animal()
// console.log(Cat)
// console.log(Cat.prototype)
// console.log(Cat._proto_)
var c1=new Cat()
var c2=new Cat()
console.log(c1.__proto__==Cat.prototype ); //true
Cat.prototype.__proto__==Animal.prototype //true
Animal.prototype.__proto__==prototype //true
console.log( c1.__proto__.__proto__==Animal.prototype); //true
Object.prototype.__proto__==null //原型链结束 true
(4)每个对象都有一个"__proto__"内部隐藏属性,
指向它所对应的原型对象(chrome--[[]] fireFox--<>)
(5)原型链利用原型上一个引用类型继承另一个引用类型的方法,
原型链正是基于"__proto__"才得以形成
(6)console.log(Object.prototype.__proto__==null);//true
原型链结束 指向空的时候
4.(借用)构造函数继承 Animal.call(this.arg)
function Animal(val){
this.name=val
this.friends=["a","b"]
this.say=function(){console.log("say...")}
}
function Person(arg){
Animal.call(this.arg) //继承
}
var p1=new Person("zs")
var p2=new Person("ls")
console.log(p1.name);
console.log(p2.name);
p1.friends.push("ww")
console.log(p1.friends);
console.log(p2.friends);
console.log(p1.say==p2.say); //false
总结:
核心:借用父类的构造函数,来增强子类的实例,完全没有使用原型
优点:1.解决了子类实例共享父类引用实例的问题
2.创建子类时,可以向父类构造函数传参
缺点:无法实现函数的复用,每一个子类实例都有一个新的function函数,消耗内存
5.组合继承(构造函数+原型链)
function Animal(val){
this.name=val
this.friends=["a","b"]
}
Animal.prototype.say=function(){console.log("say...")}
function Person(arg){
Animal.call(this,arg) //继承父类基本属性和引用属性并保留了传参的优点
}
Person.prototype=new Animal()//继承父类函数,实现函数复用
var p1=new Person("zs")
console.log(p1.name) //zs
console.log(p1.friends);
p1.friends.push=("ww")
console.log(p1.friends);
var p2=new Person("ls")
console.log(p2.name)
console.log(p2.friends)
console.log(p1.say==p2.say); //true
总结:
核心:把实例函数都放在原型对象上,以实现函数复用,并保留构造函数的优点
优点:1.不存在引用属性共享问题
2.可以传参
3.函数可以复用
缺点:因为父类构造函数被调用了两次,生成了两份,浪费内存
6.原型式继承
function Beget(obj){ // 生孩子函数
function F(){}
F.prototype=obj
return new F()
}
function Animal(){
this.name="animal"
this.friends=["ls","ww"]
}
var Person=new Animal()
var p1=Beget(Person)
// var Person={name:"zs",friends:["ls","ww"]}
var p1=Beget(Person)
console.log(p1.name) // animal
p1.name="zs"
console.log(p1.name); // zs
p1.friends.push("sl")
console.log(p1.friends) // ['ls', 'ww', 'sl']
var p2=Beget(Person)
console.log(p2.name) // animal
console.log(p2.friends); // ['ls', 'ww', 'sl']
核心:用生孩子函数得到一个"纯洁"的(没有实例属性)的新对象
7.寄生式继承
function Beget(obj){ // 生孩子函数
function F(){}
F.prototype=obj
return new F()
}
function Animal(){
this.name="animal"
this.friends=["ls","ww"]
}
function getSubObject(obj){
var clone=Beget(obj)
clone.age=23
return clone
}
var Person=getSubObject(new Animal())
console.log(Person.name) // animal
console.log(Person.age) // 23
8.寄生组合式继承 ---最佳
function Beget(obj){ // 生孩子函数
function F(){}
F.prototype=obj
return new F()
}
function Animal(){
this.name="animal"
this.friends=["ls","ww"]
}
Animal.prototype.say=function(){console.log("say...")}
function Person(){
Animal.call(this)
}
var P=Beget(Animal.prototype)
P.constructor==Person
Person.prototype=P
var p1=new Person()
console.log(p1.name)
console.log(p1.friends)
优点:完美
缺点:无