小红书阅读笔记~第六章(面向对象)

JS中对象的定义:无序属性的集合,其属性值可以包含基本值,对象或者函数。我们可以把js的对象想象成散列表,无非就是一组键值对,其中的值可以是数据或函数。

属性有两种类型:数据属性和访问器属性。
数据属性:包含一个数据值的位置,在这个位置可以读取和写入值。数据属性有四个特性:
  • configurable 属性能否delete掉,属性特性能否修改,能否把数据属性变为访问器属性

  • enumerable 能否通过for in循环返回属性

  • writable 能否修改属性的值

  • value 属性的数据值

var person = {};
  //person的name属性值为Jack 不可修改值
  Object.defineProperty(person,"name",{
      writable:false,
      value:"Jack"
  });
  alert(person.name);
  person.name="Grey";
  alert(person.name);
  Object.defineProperty(person,"age",{
      configurable:false,
      value:22
  })
  alert(person.age);
  delete person.age;//configurable为false,不能修改
  alert(person.age);
访问器属性:不包含数据值,它们包含一对getter和setter函数。
configurable 属性能否delete掉,属性特性能否修改,能否把数据属性变为访问器属性
enumerable 能否通过for in循环返回属性
get 读取属性时调用的函数
set 写入属性时调用的函数
访问器属性不能直接定义,需通过defineProperty来定义。在调用该方法时,如果不指定,configurable,enumerable,writable特性的默认值都是false
var book={
    _year:2004,
    edition:1
  };
  Object.defineProperty(book,"year",{
      get:function(){
          return this._year;
      },
      set:function(newValue){
          if(newValue>2004){
              this._year=newValue;
              this.edition+=newValue-2004;
          }
      }
  });
  book.year=2006;
  alert(book.edition);
  book._year=2007;//直接设置下划线属性的值也会起作用
_year前面的下划线是一种常用的记号,用于表示只能通过对象方法定义的属性。_year是数据属性,year是访问器属性
定义多个属性 通过描述符一次定义多个属性,第一个参数是要修改的对象,第二个对象的属性与第一个对象中要添加或修改的属性一一对应
  var book={};
    Object.defineProperties(book,{
        _year:{
            value:2004
        },
        edition:{
            value:1
        },
        year:{
            get:function(){
                return this._year;
            },
            set:function(){
                if(arguments[0]>2004){
                    this._year=arguments[0];
                    this.edition+=arguments[0]-2004;
                }
            }
        }

    })
  var des=Object.getOwnPropertyDescriptor(book,"_year");
    console.log(des);//读取属性描述符

创建对象

工厂模式

 function createPerson(name,age,job){
    var o=new Object();
    o.name=name;
    o.age=age;
    o.job=job;
    o.sayname=function(){
        alert(this.name);
    };
    return o;
  }
  var person1=createPerson("jack",22,"worker");
  person1.sayname();
  console.log(person1);
  alert(person1 instanceof Object);//工厂模式的坏处,无法确定对象类型,都是Object

构造函数模式

  function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;
    this.sayname=function(){
        alert(this.name);
    }
  }
  var person1 = new Person("jack",33,"workers")
  person1.sayname();
  console.log(person1);
  alert(person1 instanceof Person);//构造函数可以确定对象类型 但是实例上每个方法都要在实例上创建一遍

原型模式

我们创建的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,这个对象包含特定类型的所有实例共享的属性和方法。
  function Person(){

  }
  Person.prototype.name="jack";
  Person.prototype.age=29;
  Person.prototype.job="coder";
  Person.prototype.sayname=function(){
    alert(this.name);
  }
  var person1 = new Person();
  person1.sayname();//jack
  var person2 = new Person();
  person2.name="lucy";
  person2.sayname();//lucy
  person1.sayname();//jack

无论什么时候,只要创建一个新函数,就会为该函数创建一个prototype属性,这个属性指向函数的原型对象。而原型对象里也有一个constructor指针指向该函数。当用函数创建一个新实例以后,这个实例的内部的proto指针将指向原型。
console.log(Object.getPrototypeOf(person1));//实例对应的原型

每当读取某个对象的某个属性时,搜索首先从对象实例本身开始,如果找到了则返回对应的值,找不到到原型对象里找。
我们在实例对象里添加一个属性,即使和原型里的某个属性重名,也不会覆盖原型里的属性。
person1.city="beijing";
alert(person1.hasOwnProperty('city'));//属性在实例中返回true true
alert(person1.hasOwnProperty('name'));//false

in 只要属性能找到就返回true
alert("job" in person1);
for(var p in person1){//遍历所有属性,包括原型中的
    alert(p);
}
alert(Object.keys(person1));//返回所有属性组成的字符串,不包含原型

字面量重写原型对象

function Person(){}
//字面量重写原型对象
Person.prototype={
    constructor:Person//重写设定指针
    name:"jack",
    age:29,
    job:"coder",
    sayName:function(){
        alert(this.name);
    }
}

原型中查找值的过程是一次搜索,因此我们对原型对象所做的任何修改都能立即从实例上反应出来,即使先创建实例后修改原型也照样如此。
原型模式的缺点:如果属性是引用类型,一个实例的修改会导致所有实例的值都被修改。
创建自定义类型的最常见方式是组合使用构造函数模式和原型模式。(实例属性用构造,方法和共享属性用原型)

function Person(name,age,job){
    this.name=name;
   this.age=age;
    this.job=job;
    this.friends=["lucy","bob"];
}
Person.prototype={
    constructor:Person,
    sayName:function(){
        alert(this.name);
    }
}
var person1=new Person("jack",22,"worker");

继承

主要依靠原型链来完成
让某个实例的原型对象等于另一类型的实例。
function Person(name,age,job){
    this.name=name;
   this.age=age;
    this.job=job;
    this.friends=["lucy","bob"];
}
Person.prototype={
    constructor:Person,
    sayName:function(){
        alert(this.name);
    }
}
function Student(school){
    this.school=school;
}
Student.prototype=new Person();
Student.prototype.saySchhol=function(){
    alert(this.school);
};
var s1=new Student("ustc");
s1.name="jack";
s1.age=12;
s1.sayName();
console.log(s1);

原型链的问题:一 父类的引用属性,子类一但修改,所有子类实例的值都会变化,二 无法向父类传递构造参数。

借用构造函数

在子类的构造函数内部调用父类构造函数
function Student(school){
    Person.call(this);//每个子类都会有父类属性的拷贝副本
    this.school=school;
}

组合继承

使用原型链实现对原型属性和方法的继续,而借用构造函数来实现对实例属性的继承。
function  Person(name){
     this.name=name;
 }
 Person.prototype.sayname=function(){
     alert(this.name);
 }
function Student(name,school,score){
    Person.call(this,name);
    this.school=school;
    this.score=score;
}
Student.prototype=new Person("Jack");
Student.saySChool=function(){
    alert(this.school);
}
var s1=new Student("lucy","ustc",99);
var s2=new Student("mike","autc",80);
console.log(s1);
console.log(s2);
s1.sayname();
s2.sayname();

寄生式继承

增强原型式继承的功能的一种模式
缺点:使用寄生式继承来为对象添加函数,会由于不能做到函数复用而降低效率,这一点与构造函数模式类似。
const createAnother = function(original){
  const clone = object(original)
  clone.sayHi = function(){
    console.log('hi')
  }
  return clone
}
const person = {
  name: 'Nicholas',
  friends: ['Shelby', 'Court', 'Van']
}
const anotherPerson = createAnother(person)
anotherPerson.sayHi() //hi

寄生组合式继承

所谓寄生组合式继承,就是借用构造函数来继承属性
const object = function(o){
  function F(){}
  F.prototype = o
  return new F()
}
const inheritPrototype = function(Child, Parent){
  const prototype = object(Parent.prototype)
  prototype.constructor = Child
  Child.prototype = prototype
  Child.__proto__ = Parent
}
function Parent(name) {
  this.name = name
}

Parent.sayHello = function (){
    console.log('hello')
}

Parent.prototype.sayName = function() {
    console.log('my name is ' + this.name)
    return this.name
}


function Child(name, age) {
    Parent.call(this, name)
    this.age = age
}

inheritPrototype(Child, Parent)

Child.prototype.sayAge = function () {
    console.log('my age is ' + this.age)
    return this.age
}

明天开始第七章 函数表达式

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容

  • 面向对象的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。ECMAScr...
    DHFE阅读 971评论 0 4
  •   面向对象(Object-Oriented,OO)的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意...
    霜天晓阅读 2,107评论 0 6
  • 第3章 基本概念 3.1 语法 3.2 关键字和保留字 3.3 变量 3.4 数据类型 5种简单数据类型:Unde...
    RickCole阅读 5,124评论 0 21
  • 【7月度检视】 0731/2019如何过一天就是如何过一生【2019年度目标关注点】 ①养成早睡早起的习惯 ②每天...
    将军_e9fb阅读 48评论 0 0
  • 今天我和朋友约好下个3点一起玩,就在她家小区门口集合。 下午3点的时候我们在她家小区门口集合。我们先去...
    梦灵紫洛阅读 180评论 0 4