js-面向对象02

一、对象的属性设置—defineProperty

1、Object.getOwnPropertyDescriptor() 获取对象属性

var Person={
    name="zs"
}
var des=Object.getOwnPropertyDescriptor()
console.log(des.value)   //zs
console.log(des.configurable)  //true
console.log(des.writable)     //true
console.log(des.enumerable)   //true

2、对象的数据属性

  • value 属性的属性值
  • configurable 能否删除属性的值
  • writable 能否修改实现的值
  • enumerable 能否遍历(枚举)属性的值

(0)var Person={}

Object.defineProperty(Person,"name",{value:"zs",writable:false})
 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

(1)var Person={}

Object.defineProperty(Person,"name",{value:"zs",writable:false})

(2)var Person={}

Object.defineProperty(Person,"name",{value:"zs",writable:true,enumerable:true})
 Object.defineProperty(Person,"age",{value:23,enumerable:false})
 var v1=Object.keys(Person)
 console.log(v1) [name]

3、对象的访问属性

(1)get:在读取属性时调用的函数
(2)set:在写入属性时调用的函数

var Person={"_name":"zs"}
   Object.defineProperty(Person,"name",
   {get:function(){
    console.log("get....") 
    return this._name
},
    set:function(val){
        console.log("set...",val)
    }
})
//    console.log(Person.name)
Person.name="ls"

注:

var Person={"_name":"zs",age:23}
var v1=""
Object.defineProperty(Person,"name",
        { get:function(){
                console.log("get....")
                //return "ls"
                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)

二、继承

1、约定

  function Person(){ 
     var name="zs"      //私有的基本属性
     var friends=["ls","ww"] //私有的引用属性
     function f1(){}    //私有的函数
  }
function Person(){
  this.name="zs"          //实例的基本属性
  this.friends=["ls","ww"] //实例的引用属性
  this.f1=function(){}   //实例的函数
}
function Person(){}
  Person.prototype.name="zs"          //原型的基本属性
  Person.prototype.friends=["ls","ww"] //原型的引用属性
  Person.prototype.f1=function(){}   //原型的函数

2、原型链继承

创建一个对象,Animal,构造函数+原型
name 引用类型 方法say eat

function Animal(){
            this.name="animal"
            this.friends=['wb','b']
            this.say=function(){
                console.log("say...");
            }
        }
        Animal.prototype.eat=function(){  console.log("eat..."); }

function cat(){}
//继承
cat.prototype=new Animal()
cat.prototype.name="cat"

//实例
var c1=new cat()
c1.name="jfcat"
console.log(c1.name)
c1.say()
c1.friends.push("ifcat01")

var c2=new cat()
console.log(c2.name)
console.log(c1.friends) ['wb', 'b', 'ifcat01']

总结:
核心: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"属性,指向函数本身

// var a1=new Animal()
// console.log(a1)
// console.log(a1.__proto__)
// console.log(a1.prototype) //undefiend

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(c1.__proto__.__proto__==Animal.prototype)//true
console.log(Object.prototype.__proto__==null)//true //原型链结束

(3)new创建的原型对象没有原型(prototype)属性
(4)每个对象都有一个"__proto__“内部隐藏属性,
指向他所对应的原型对象(chrome–[[]] firefox–<>)
(5)原型链利用原型上一个引用类型继承另一个引用类型的方法
原型链正是基于”__proto__"才得以形成
(6)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")
            console.log(p1.name) //zs
            p1.friends.push("ww")
            var p2=new Person("ls")
            console.log(p2.name) //ls
            console.log(p2.friends) //["a","b"]
            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
   p1.friends.push("ww")
   var p2=new Person("ls")
    console.log(p2.name)   //ls
    console.log(p2.friends) //[a,b]
    console.log(p1.say==p2.say) //true

总结:
核心:把实例函数放在原型对象上,以实现函数复用,并保留构造函数的优点
优点:

  • 不存在引用属性共享问题

  • 可传参

  • 函数可复用

缺点:有误父类的构造函数被调用了两次,浪费内存

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)
console.log(p1.name)  //animal
p1.name="zs"
p1.friends.push("zl")
var p2=Beget(Person)
console.log(p2.name)  //animal
console.log(p2.friends) //["ls","ww","zl"]

核心:用生孩子函数的到一个“纯洁”的(没有实例属性)的新对象

7.

function Beget(obj){ //生孩子函数
        function f(){ }
        f.prototype=obj
        return new f()
     }
       function Animal(){
        this.name="animal"
        this.friebds=["ls","ww"]
       }
   function getSubObject(obj){
    var clone=Beget(obj)
    clone,age=23
    return clone
   }
var Person=getSubObject(new Animal())
Person.name  //animal
Person.age //23

8.寄生组合式继承 —最佳

function Beget(obj){ //生孩子函数
        function f(){ }
        f.prototype=obj
        return new f()
     }
       function Animal(){
        this.name="animal"
        this.friebds=["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 ) //animal 
   console.log(p1.friebds) ["ls","ww"]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值