JavaScript 面向对象的程序设计1

一、理解对象

1.创建一个对象,然后给这个对象新建属性和方法。
①常见的创建方式

var person = new Object(); //创建一个Object 对象person.name = 'XIE'; //创建一个name 属性并赋值person.age = 20; //创建一个age 属性并赋值person.sayName = function () { //创建一个run()方法并返回值return this.name; //this指的是person本身};

②字面量的形式

var person = {name:"xie",age:20,job:"学生",sayName:function(){return this.name;}
}

2.数据属性
数据属性有4个描述其行为的特性。

特性默认值含义
configurabletrue是否可配置,表示能否删除属性重新定义,能否修改属性的特性,能否修改为访问器属性。
enumerabletrue是否可枚举
writabletrue是否可修改属性值
valueundefined属性的数据值

注:configurable特性一旦设置为false后,则不能再变为true.

var person={};
Object.defineProperty(person,"name",{configurable:true,enumerable:true,writable:true,value:"xie"
})

3.访问器属性

特性默认值含义
configurabletrue是否可配置,表示能否删除属性重新定义,能否修改属性的特性,能否修改为访问器属性。
enumerabletrue是否可枚举
getundefined读取属性时调用
setundefined写入属性时调用

二、创建对象

1.工厂模式

function createObject(name, age) { //集中实例化的函数var obj = new Object();obj.name = name;obj.age = age;obj.run = function () {return this.name + this.age + '运行中...';};return obj;
}
var box1 = createObject('Lee', 100); //第一个实例
var box2 = createObject('Jack', 200); //第二个实例

工厂模式解决了重复实例化的问题,但还有一个问题,那就是识别问题,因为根本无法弄清楚一个对象的类型。

2.构造函数模式

function Person(name,age){this.name = name;this.age = age;this.run = function(){alert(this.name);}
}
var person1 = new Person("Lee",100);
var person2 = new Person("Jack",200);

使用了构造函数的方法,和使用工厂模式的方法他们不同之处如下:

  1. 构造函数方法没有显示的创建对象(new Object());
  2. 直接将属性和方法赋值给this 对象;
  3. 没有renturn 语句。

构造函数的方法有一些规范:

  • .函数名和实例化构造名相同且大写,(PS:非强制,但这么写有助于区分构造函数和普通函数);
  • 通过构造函数创建对象,必须使用new 运算符。

使用new操作符创建实例时,执行过程如下:

  1. 创建一个新对象;
  2. 将构造函数的作用域赋给新对象(因此this就指向了这个对象);
  3. 执行构造函数中的代码(为这个新对象添加属性);
  4. 返回新对象

    使用构造函数的主要问题,就是每个方法都要再每个实例上重新创建一遍。通过下面可知不一样:

alert(person1.run == person2.run);  //false

3.原型模式

我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法。使用原型的好处可以让所有对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中定义对象信息,而是可以直接将这些信息添加到原型中。

3.1常见的语法

// 原型模式
function Box() {} //声明一个构造函数
Box.prototype.name = 'Lee'; //在原型里添加属性
Box.prototype.age = 100;
Box.prototype.run = function () { //在原型里添加方法return this.name + this.age + '运行中...';
};
//比较一下原型内的方法地址是否一致:
var box1 = new Box();
var box2 = new Box();
alert(box1.run == box2.run); //true,方法的引用地址保持一致

下面可通过图进一步了解

构造函数模式

原型模式
在原型模式声明中,多了两个属性,这两个属性都是创建对象时自动生成的。proto属性是实例指向原型对象的一个指针,ECMAScript5称这个指针为[[Prototype]],它的作用就是指向构造函数的原型属性constructor。

isPrototypeOf()方法来判断一个对象是否指向了该构造函数的原型

alert(Box.prototype.isPrototypeOf(box1)); //true,只要实例化对象,即都会指向

Object.getPrototype()方法返回[[Prototype]]的值。IE9+,Firefox3.5+,Safari5+,Opera12+ 和Chrome支持

alert(Object.getPrototype(box1).name);  //Lee

原型模式的执行流程:

  1. .先查找构造函数实例里的属性或方法,如果有,立刻返回;
  2. 如果构造函数实例里没有,则去它的原型对象里找,如果有,就返回;

hasOwnProperty()函数判断构造函数的实例中是否有该属性。

alert(box.hasOwnProperty('name')); //实例里有返回true,否则返回false

in操作符会在通过对象能够访问给定属性时返回 true,无论该属性存在于实例中还是原型中。

alert('name' in box); //true,存在实例中或原型中
function isProperty(object, property) { //判断原型中是否存在属性return !object.hasOwnProperty(property) && (property in object);
}

3.2更简单的原型语法

为了让属性和方法更好的体现封装的效果,并且减少不必要的输入,原型的创建可以使用字面量的方式:

function Box() {};
Box.prototype = { //使用字面量的方式name : 'Lee',age : 100,run : function () {return this.name + this.age + '运行中...';}
};

使用构造函数创建原型对象和使用字面量创建对象在使用上基本相同,但还是有一些区别,字面量创建的方式使用constructor 属性不会指向实例,而会指向Object,构造函数创建的方式则相反。

var box = new Box();
alert(box instanceof Box);  //true
alert(box instanceof Object);  //true
alert(box.constructor == Box); //字面量方式,返回false,否则,true
alert(box.constructor == Object); //字面量方式,返回true,否则,false

如果想让字面量方式的constructor 指向实例对象,可以如下所示

function Box() {};
Box.prototype = { //使用字面量的方式constructor : Box, //直接强制指向即可name : 'Lee',age : 100,run : function () {return this.name + this.age + '运行中...';}
};

重设constructor会导致它的enumerable特性被修改为true,默认情况下,原生的constructor是不可枚举的,可使用Object.defineProperty()方法重设构造函数。

Object.defineProperty(Box.prototype,"constructor",{enumerable:false,value:Box
});

原型的声明是有先后顺序的,所以,重写的原型会切断之前的原型。

function Box() {};
Box.prototype = { //原型被重写了constructor : Box,name : 'Lee',age : 100,run : function () {return this.name + this.age + '运行中...';}
};
Box.prototype = {age = 200
};
var box = new Box(); //在这里声明
alert(box.run()); //erroe,因为box 只是最初声明的原型

3.3原型对象的问题

原型模式创建对象也有自己的缺点,它省略了构造函数传参初始化这一过程,带来的缺点就是初始化的值都是一致的。而原型最大的缺点就是它最大的优点,那就是共享。原型中所有属性是被很多实例共享的,共享对于函数非常合适,对于包含基本值的属性也还可以。但如果属性包含引用类型,就存在一定的问题:

function Box() {};
Box.prototype = {constructor : Box,name : 'Lee',age : 100,family : ['父亲', '母亲', '妹妹'], //添加了一个数组属性run : function () {return this.name + this.age + this.family;}
};
var box1 = new Box();
box1.family.push('哥哥'); //在实例中添加'哥哥'
alert(box1.run());
var box2 = new Box();
alert(box2.run()); //共享带来的麻烦,也有'哥哥'了

4.动态原型模式

为了解决构造传参和共享问题,可以组合构造函数+原型模式,即动态原型模式。

function Box(name ,age) { //将所有信息封装到函数体内this.name = name;   //不共享的使用构造函数形式this.age = age;if (typeof this.run != 'function') { //仅在第一次调用的初始化Box.prototype.run = function () {   //共享的使用原型模式return this.name + this.age + '运行中...';};}
}
var box = new Box('Lee', 100);
alert(box.run());

当第一次调用构造函数时,run()方法发现不存在,然后初始化原型。当第二次调用,就不会初始化,并且第二次创建新对象,原型也不会再初始化了。这样及得到了封装,又实现了原型方法共享,并且属性都保持独立。
PS:使用动态原型模式,要注意一点,不可以再使用字面量的方式重写原型,因为会切断实例和新原型之间的联系。

5.寄生构造函数模式

寄生构造函数,其实就是工厂模式+构造函数模式。这种模式比较通用,但不能确定对象关系。

function myString(string) {var str = new String(string);str.addstring = function () {return this + ',被添加了!';};return str;
}
var box = new myString('Lee'); //比直接在引用原型添加要繁琐好多
alert(box.addstring());

使用场景:要创建一个具有额外方法的引用类型时。

6.稳妥构造函数模式

在一些安全的环境中,比如禁止使用this 和new,这里的this 是构造函数里不使用this,这里的new 是在外部实例化构造函数时不使用new。

function Box(name , age) {var obj = new Object();obj.run = function () {return name + age + '运行中...'; //直接打印参数即可};return obj;
}
var box = Box('Lee', 100); //直接调用函数
alert(box.run());

PS:稳妥构造函数和寄生类似。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/249696.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Zookeeper 使用

安装和配置详解 本文介绍的 Zookeeper 是以 3.2.2 这个稳定版本为基础,最新的版本可以通过官网 http://hadoop.apache.org/zookeeper/来获取,Zookeeper 的安装非常简单,下面将从单机模式和集群模式两个方面介绍 Zookeeper 的安装和配置。 单…

Asp.Net Core 工作单元 UnitOfWork UOW

Asp.Net Core 工作单元示例 来自 ABP UOW 去除所有无用特性 代码下载 : 去除所有无用特性版本,原生AspNetCore实现 差不多 2278 行代码: 链接:https://pan.baidu.com/s/1NoEIDSAPNr46xNHYEx9KCA 提取码:570i 包含C…

网站性能优化--CRP

网站性能优化–CRP 为了把HTML、CSS和JavaScript转化成活灵活现、绚丽多彩的网页,浏览器需要处理一系列的中间过程,优化性能其实就是了解这个过程中发生了什么-即CRP(Critical Rendering Path,关键渲染路径)。首先,我们从头开始快…

Dubbo+zookeeper基础讲解

一、dubbo是什么? 1)本质:一个Jar包,一个分布式框架,,一个远程服务调用的分布式框架。 既然是新手教学,肯定很多同学不明白什么是分布式和远程服务调用,为什么要分布式,为什么要远程调用。我简…

What Are You Talking About HDU1075

一开始我也想用map 但是处理不好其他字符。。 看了题解 多多学习&#xff01; 很巧妙 就是粗暴的一个字符一个字符的来 分为小写字母和非小写字母两个部分 一但单词结束的时候就开始判断。 #include<bits/stdc.h> using namespace std;int main() {string a,b;map&l…

学习File API用于前端读取文件

1. File API简介 File API对于某些专门的网站的不可或缺的。现在常用它实现对文件的预览等功能。 File API规定怎么从硬盘上提取文件&#xff0c;直接交给在网页中运行中的Javascript代码。然后代码可以打开文件探究数据&#xff0c;无论是本地文件还是其他文件。注意&#x…

Dubbo入门教程

服务端&#xff08;dubbo-server&#xff09; 1. pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaL…

NSAssert和NSParameterAssert

2016.05.05 18:34* 字数 861 阅读 5127评论 0喜欢 17https://www.jianshu.com/p/3072e174554fNSAssert和NSParameterAssert在开发环境中经常被使用&#xff0c;调试和验证代码参数的完整性&#xff0c;断言为真&#xff0c;则表明程序运行正常&#xff0c;而断言为假&#xff0…

使用Nodejs发送邮件

尝试用了Nodemailer来发送邮件&#xff0c;结果成功了&#xff0c;虽然是相对比较简单的&#xff0c;但还是记录一下吧。 Nodemailer 是 Node.js 应用程序的一个模块&#xff0c;可以方便地发送电子邮件。 使用 # 初始化 pageage.json 文件 $ npm init # 安装依赖 $ npm ins…

Spring Cloud 微服务架构

一、分布式服务框架的发展 1.1 第一代服务框架   代表&#xff1a;Dubbo(Java)、Orleans(.Net)等 特点&#xff1a;和语言绑定紧密 1.2 第二代服务框架   代表&#xff1a;Spring Cloud等 现状&#xff1a;适合混合式开发&#xff08;例如借助Steeltoe OSS可以让ASP.Ne…

JZOJ 4421. aplusb

4421. aplusb Time Limits: 1000 ms Memory Limits: 524288 KB Detailed Limits Goto ProblemSetDescription SillyHook要给小朋友出题了&#xff0c;他想&#xff0c;对于初学者&#xff0c;第一题肯定是ab 啊&#xff0c;但当他出完数据后神奇地发现.in不见了&#xff0c…

计算机网络(十),HTTP的关键问题

目录 1.在浏览器地址栏键入URL&#xff0c;按下回车之后经历的流程 2.HTTP状态码 3.GET请求和POST请求的区别 4.Cookie和Session的区别 5.IPV4和IPV6 十、HTTP的关键问题 1.在浏览器地址栏键入URL&#xff0c;按下回车之后经历的流程 &#xff08;1&#xff09;DNS解析 &#x…

vue中 mock使用教程

//mock/index.js import Mock from mockjs //引入mockjs&#xff0c;npm已安装 import { Random,toJSONSchema } from mockjs // 引入random对象,随机生成数据的对象&#xff0c;&#xff08;与占位符一样&#xff09; Mock.setup({timeout:1000 //设置请求延时时间 }) const …

WinSxS文件夹瘦身

WinSxS文件夹瘦身2014-5-8 18:03:32来源&#xff1a;IT之家作者&#xff1a;阿象责编&#xff1a;阿象 评论&#xff1a;27刚刚&#xff0c;我们分享了如何用DISM管理工具查看Win8.1 WinSxS文件夹实际大小。对于WinSxS文件夹&#xff0c;几乎每个Windows爱好者都认识到其重要性…

bcrypt的简单使用

前段时间在捣鼓个人项目的时候用到了nodejs做服务端&#xff0c;发现使用加密的方法和之前常用的加密方式不太一致&#xff0c;下面以demo的形式总结一下bcrypt对密码进行加密的方法。 一、简介 Bcrypt简介&#xff1a; bcrypt是一种跨平台的文件加密工具。bcrypt 使用的是布…

HTTP协议学习笔记

1.HTTP协议简介 &#xff08;1&#xff09;客户端连上web服务器后&#xff0c;若想获得web服务器中的某个web资源&#xff0c;需遵守一定的通讯格式&#xff0c;HTTP协议用于定义客户端与web服务器通迅的格式。 &#xff08;2&#xff09;HTTP是hypertext transfer protocol&…

defer和async的原理与区别

上一篇刚转载了一篇有关于网站性能优化的文章&#xff0c;其中提及到了页面的加载和渲染的过程&#xff0c;提到了defer和async的相关区别&#xff0c;但是本人在此之前并没有深究其中的区别。 defer和async是script标签的两个属性&#xff0c;用于在不阻塞页面文档解析的前提…

一些奇妙的线段树操作

学过数据结构和会做题完全是两个概念orz 各种各样的题目都应该见识一下 简单的目录&#xff1a; 最大连续长度 吉司机线段树 线段树合并/分裂 最大连续长度问题 典型题目&#xff1a;HDU 3911 &#xff08;$Black$ $And$ $White$&#xff09; 题目大意&#xff1a;有一个长度为…

微服务实践沙龙-上海站

微服务的概念最早由Martin Fowler与James Lewis于2014年共同提出&#xff0c;核心思想是围绕业务能力组织服务&#xff0c;各个微服务可被独立部署&#xff0c;服务间是松耦合的关系&#xff0c;以及数据和治理的去中心化管理。微服务能够帮助企业应对业务复杂、频繁更新以及团…

(四)RabbitMQ消息队列-服务详细配置与日常监控管理

&#xff08;四&#xff09;RabbitMQ消息队列-服务详细配置与日常监控管理 原文:&#xff08;四&#xff09;RabbitMQ消息队列-服务详细配置与日常监控管理RabbitMQ服务管理 启动服务&#xff1a;rabbitmq-server -detached【 /usr/local/rabbitmq/sbin/rabbitmq-server -deta…