资讯专栏INFORMATION COLUMN

高程3总结#第6章面向对象的程序设计

ingood / 593人阅读

摘要:面向对象的程序设计理解对象属性类型创建自定义对象的最简单方式就是创建一个的实例,然后再为它添加属性和方法对象字面量称为创建这种对象的首选方式两种属性数据属性,可以读取和写入值,有四个描述其行为的特性表示能否通过删除属性从而重新定义属性,能否

面向对象的程序设计 理解对象 属性类型

创建自定义对象的最简单方式就是创建一个Object的实例,然后再为它添加属性和方法

var person=new Object();
person.name="Nicholas";
person.age=20;
person.job="Software Engineer";
person.sayName=function(){
  alert(this.name)
}

对象字面量称为创建这种对象的首选方式

var person={
  name:"Nicholas",
  age:20,
  job:"Software Engineer",
  sayName:function(){
    alert(this.name);
  }
};

两种属性

数据属性,可以读取和写入值,有四个描述其行为的特性

[[Configurable]]表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性,特性默认值为true

[[Enumerable]]表示能否通过for-in循环返回属性,特性默认值为true

[[Writable]]表示能否修改属性的值,特性默认值为true

[[Value]]包含这个属性的数据值,读取属性值的时候,从这个位置读,写入属性值的时候,把新值保存在这个位置,特性默认值是undefined

要修改属性默认的特性,使用Object.definePropery()方法,这个方法接收三个参数:属性所在的对象、属性的名字和一个描述符对象。

var person={};
Object.definePropery(person,"name",{
  writable:false,
  value:"Nicholas"
});
alert(person.name);//"Nicholas"
person.name="Greg";
alert(person.name);//"Nicholas"

访问器属性,包含一对getter和setter函数。在读取访问器属性的时候,会调用getter函数,这个函数负责返回有效的值。在写入访问器属性的时候,会调用setter函数并传入新值,这个函数负责决定如何处理数据。

[[Configurable]]表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属性,特性默认值为true

[[Enumerable]]表示能否通过for-in循环返回属性,特性默认值为true

[[Get]]在读取属性时调用的函数,默认值为undefined

[[Set]]在写入属性时调用的函数,默认值为undefined

访问器属性不能直接定义,必须使用Object.defineProperty()来定义

定义多个属性

Object.defineProperties()方法可以通过描述符一次定义多个属性,这个方法接收两个对象参数,一个对象是要添加和修改其属性的对象,第二个对象的属性与第一个对象中要添加或修改的属性一一对应

var book = {};
Object.defineProperties(book, {
  _year: {
    value: 2004
  },
  edition: {
    value: 1
  },
  year: {
    get: function(){
      return this._year;
    },
    set: function(newValue){
      if (newValue > 2004) {
        this._year = newValue;
        this.edition += newValue - 2004;
      }
    }
  }
});

读取属性的特性

Object.getOwnPropertyDescription()方法,可以取得给定属性的描述符,这个方法接收两个参数,属性所在的对象和要读取其描述符的属性名称

var book = {};
Object.defineProperties(book, {
  _year: {
    value: 2004
  },
  edition: {
    value: 1
  },
  year: {
    get: function(){
      return this._year;
    },
    set: function(newValue){
      if (newValue > 2004) {
        this._year = newValue;
        this.edition += newValue - 2004;
      }
    }
  }
});
var descriptor = Object.getOwnPropertyDescriptor(book, "_year");
alert(descriptor.value); //2004
alert(descriptor.configurable); //false
alert(typeof descriptor.get); //"undefined"
var descriptor = Object.getOwnPropertyDescriptor(book, "year");
alert(descriptor.value); //undefined
alert(descriptor.enumerable); //false
alert(typeof descriptor.get); //"function"

创建对象 工厂模式
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("Nicholas", 29, "Software Engineer");
var person2 = createPerson("Greg", 27, "Doctor");
构造函数模式
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
  alert(this.name);
};
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");

只要通过new操作符来调用,那它就可以作为构造函数

// 当作构造函数使用
var person = new Person("Nicholas", 29, "Software Engineer");
person.sayName(); //"Nicholas"
// 作为普通函数调用
Person("Greg", 27, "Doctor"); // 添加到 window
window.sayName(); //"Greg"
// 在另一个对象的作用域中调用
var o = new Object();
Person.call(o, "Kristen", 25, "Nurse");
o.sayName(); //"Kristen"

原型模式
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Nicholas"
var person2 = new Person();
person2.sayName(); //"Nicholas"
alert(person1.sayName == person2.sayName); //true

无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象,默认情况下,所有的原型对象都会自动获得一个constructor属性,这个属性包含一个指向prototype属性所在函数的指针。



组合使用构造函数模式和原型模式
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Shelby", "Court"];
}
Person.prototype = {
constructor : Person,
sayName : function(){
  alert(this.name);
}
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Count,Van"
alert(person2.friends); //"Shelby,Count"
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true
动态原型模式
function Person(name, age, job){
//属性
this.name = name;
this.age = age;
this.job = job;
// 方法
if (typeof this.sayName != "function"){
  Person.prototype.sayName = function(){
    alert(this.name);
  };
}
}
var friend = new Person("Nicholas", 29, "Software Engineer");
friend.sayName();
寄生构造函数模式
function Person(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 friend = new Person("Nicholas", 29, "Software Engineer");
friend.sayName(); //"Nicholas"
稳妥构造函数模式
function Person(name, age, job){
//创建要返回的对象
var o = new Object();
//可以在这里定义私有变量和函数
//添加方法
o.sayName = function(){
  alert(name);
};
//返回对象
return o;
}
继承 原型链


可以通过两种方式来确定原型和实例之间的关系,第一种方式是使用instanceof操作符,只要这个操作符来测试实例与原型链中出现过的构造函数,结果就会返回true

alert(instance instanceof Object); //true
alert(instance instanceof SuperType); //true
alert(instance instanceof SubType); //true

第二种方式是使用isPrototypeOf()方法,只要是原型链中出现过的原型,都可以说是原型链所派生的实例的原型,因此isPrototypeOf()方法也会返回true

alert(Object.prototype.isPrototypeOf(instance)); //true
alert(SuperType.prototype.isPrototypeOf(instance)); //true
alert(SubType.prototype.isPrototypeOf(instance)); //true

借用构造函数
function SuperType(){
this.colors = ["red", "blue", "green"];
}
function SubType(){
// 继承了 SuperType
SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
var instance2 = new SubType();
alert(instance2.colors); //"red,blue,green"

对于原型链而言,借用构造函数有一个很大的优势,即可以在子类型构造函数中向超类型构造函数传递参数

function SuperType(name){
  this.name = name;
}
function SubType(){
  //继承了 SuperType,同时还传递了参数
  SuperType.call(this, "Nicholas");
  //实例属性
  this.age = 29;
}
var instance = new SubType();
alert(instance.name); //"Nicholas";
alert(instance.age); //29

组合继承

指的是将原型链和借用构造函数的技术组合到一块

function SuperType(name){
  this.name = name;
  this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
  alert(this.name);
};
function SubType(name, age){
  //继承属性
  SuperType.call(this, name);
  this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
  alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nicholas";
instance1.sayAge(); //29
var instance2 = new SubType("Greg", 27);
alert(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27

原型式继承
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = Object.create(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"
寄生式继承

思路和构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,函数在内部以某种方式来增强对象

function createAnother(original){
  var clone = object(original); //通过调用函数创建一个新对象
  clone.sayHi = function(){ //以某种方式来增强这个对象
    alert("hi");
  };
  return clone; //返回这个对象
}
var person = {
  name: "Nicholas",
  friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"

寄生组合式继承

无论什么情况下都会调用两次超类型构造函数,一次是在创建子类型原型的时候,另一次实在子类型构造函数内部

function SuperType(name){
  this.name = name;
  this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
  alert(this.name);
};
function SubType(name, age){
  SuperType.call(this, name); // 第二次调用 SuperType()
  this.age = age;
}
SubType.prototype = new SuperType(); // 第一次调用 SuperType()
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
  alert(this.age);
};

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97568.html

相关文章

  • 高程3总结#8BOM

    摘要:对象的核心对象是,它表示浏览器的一个实例。而和则表示该容器中页面视图区的大小。在中,与返回相同的值,即视口大小而非浏览器窗口大小。第三个参数是一个逗号分隔的设置字符串,表示在新窗口中都显示哪些特性。这应该是用户打开窗口后的第一个页面 BOM window对象 BOM的核心对象是window,它表示浏览器的一个实例。在浏览器中,window对象有双重角色,它既是通过JavaScript访...

    MASAILA 评论0 收藏0
  • 高程3总结#17错误处理与调试

    错误处理与调试 错误处理 try-catch语句 try{ //可能会导致错误的代码 }catch(error){ //在错误发生时怎么处理 } 发生错误时可以显示浏览器给出的信息 try{ window.someNonexistentFunction(); }catch(error){ alert(error.message); } 在try-catch语句中是可选的,但...

    fizz 评论0 收藏0
  • 高程3总结#16HTML5脚本编程

    摘要:脚本编程跨文档消息传递跨文档消息传送,简称为,指的是来自不同域的页面间传递消息的核心是方法,在规范中,除了部分之外的其他部分也会提到这个方法名,但都是为了同一个目的,向另一个地方传递参数。第一个页面加载时为空 HTML5脚本编程 跨文档消息传递 跨文档消息传送,简称为XMD,指的是来自不同域的页面间传递消息 XMD的核心是postMessage()方法,在HTML5规范中,除了XDM...

    silvertheo 评论0 收藏0
  • 高程3总结#1JavaScript简介

    摘要:简介简史诞生于年,当时主要负责表单的输入验证。实现一个完整的由三部分组成核心文档对象模型浏览器对象模型就是对实现该标准规定的各个方面内容的语言的描述。把整个页面映射为一个多层节点结构。由万维网联盟规划。主要目标是映射文档的结构。 JavaScript简介 JavaScript简史 JavaScript诞生于1995年,当时主要负责表单的输入验证。 如果没有表单验证的功能,填入信息之...

    betacat 评论0 收藏0
  • 高程3总结#20JSON

    摘要:语法语法可以表示三种类型的值简单值使用与相同的语法,可以在中表示字符串数值布尔值和。对象对象作为一种复杂数据类型,表示的是一组无序的键值对儿。如果字符串长度超过了个,结果中将只出现前个字符。 JSON 语法 JSON语法可以表示三种类型的值 简单值:使用与 JavaScript 相同的语法,可以在 JSON 中表示字符串、数值、布尔值和 null 。但 JSON 不支持 JavaS...

    Hwg 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<