Javascript基础编程の面向对象编程
javascript是解释型的语言,在编译时和运行时之间没有明显区别,因此需要更动态的方法。javascript没有正式的类的概念,我们可以使用在运行时创建新的对象类型来替代,并且可以随时更改已有对象的属性。
javascript是一种基于原型的面向对象的语言,即每个对象有个原型,对象从原型中继承属性和方法。当访问对象的属性或调用对象的方法时,解释器首先检查对象是否有个同名的实例属性或方法。如果有,就使用实例属性或方法;如果没有,解释器就检查对象的原型中是否有适当的属性或方法。在这样一个特殊的环境下,该类型(类)的所有对象公共方法和属性可以被封装在原型中,每个对象可以有代表该对象特定数据的实例属性。
在javascript中,原型关系是递归的。即,对象的原型也是一个对象,而原型的本身可能还有一个原型。这就意味着如果被访问的属性发现不是对象的实例属性,也不是对象的原型的属性,解释器将沿着原型链搜索到原型的原型。如果还没有找到,就继续沿原型链向上搜索。javascript中object是所有对象的超类,所以object是它搜索的终点。如果object中还没有找到,那么返回的值就是undefined。如果是在调用方法,则抛出error。
一、javascript面向对象基础
1、对象的创建
javascript中的对象使用一个new运算符和一个构造函数创建。构造函数是一个特殊类型的函数,它通过初始化对象要占据的内存,来准备一个新对象的使用。我们可以使用一个不带参数的构造函数,也可以使用一个带参数的构造函数,来创建对象。如:
var city = new String();
var city = new String('上海');
2、对象销毁和垃圾回收
对象和其他变量都需要使用内存,而一个计算机中内存资源是有限的。为了防止潜在的内存不足,某些编程语言强制要求程序员仔细的管理他们程序中内存的使用。幸运的是,javascript并不要求程序员管理内存。当javascript创建对象时,解释器自动给对象分配内存。当对象使用完毕后,解释器自动清理对象所用内存,即垃圾回收。
但是,如果我们的对象代码中包含了大量的数据操作,最好将不需要的数据用null来替换,以尽快释放资源。
var book = new Book();
....
大量数据操作后...
....
book = null;
如果对相同数据有多个引用,必须确保所有的引用设为null。否则,解释器将保留这些数据,以备再次需要。
3、动态添加对象属性
var obj = new Object('hello world');
alert(obj.name);//undefined
obj.name='jiajia';
alert(obj.name);//jiajia
动态添加的属性,我们称之为实例属性,之所以叫实例属性,是因为它们仅出现在它们添加到的特定对象或实例中。与此相反还有一个公共属性,比如说string的length属性,所有string对象都具有这一公共属性。实例属性有利于为了某些特殊用途对已存在的对象进行补充或扩展。
4、动态删除对象属性
var mystring = new String('hello world');
mystring.isTrue = true;
delete mystring.isTrue;
alert(mystring.isTrue);//undefined;
java程序员注意,javascript中delete与Java中不同,它仅仅用在对象中删除属性或者从数组中删除元素,但是我们不能删除对象本身。
5、动态添加对象的方法
像添加属性方式一样,方法也可以动态添加:
var mystring = new String('hello world');
function alertSay(){alert('不行');};
mystring.sayno=alertSay;
mystring.sayno();//不行
以上是添加了一个实名函数,我们还可以添加一个匿名函数:
var mystring = new String('hello world');
mystring.sayno=function(){alert('不行');};
mystring.sayno();//不行
6、对象语句
如果程序中要使用某个对象的多个属性和方法,则可以考虑使用with语句,将需要使用其属性和方法的对象用with语句包含起来,语法:
with(对象){
.....语句.....
}
例如:
with(document.myform){
if(username.value=='')
if(password.value=='')
}
for语句是一种特殊的循环语句,用于遍历一个对象的所有属性。注意是所有属性!
例如,以下示例用for...in语句遍历了document对象的所有属性,并将其显示出来:
document.write('<h3>document对象的所有属性如下:</h3>');
for(var i in document){
document.write(i+'<br/>');
}
二、创建自定义的javascript类和对象
1、工厂方式
所谓工厂方式,就是先创建对象,然后往对象中添加属性和方法。
带参批量生产:
function createPerson(name){
var personobj = new Object();
personobj.name=name;
personobj.say=function(){
alert('who is'+this.name);
}
return personobj;
}
var persion1 = createPerson('fanfan');
var persion2 = createPerson('xiaoxiao');
person1.say();//fanfan
person2.say();//xiaoxiao
随着javascript正规起来,这种创建对象的方式并不提倡了。原因有二:
(1)语义上的,即这种方式不适用new运算符创建对象;
(2)功能上的,每次调用createPerson()函数,都建一个新的函数say()。这意味着每个对象都有自己版本的say()方法。然后在现实中,每个对象都是共享相同的方法。
2、构造函数的方式
与工厂方式类似,类名的第一个字母是大写。
function Person(name){
this.name = name;
this.say = function(){
alert('who is'+name);
}
}
var person1 = new Person('fanfan');
var person2 = new Person('xiaoxiao');
我们可以看到,在构造函数内部没有创建对象,而是使用了this关键字。当用new运算符调用构造函数时,在构造函数第一行被执行之前就创建了一个对象,此时这个对象可以通过this运算符访问。然后,我们可以直接给this分配属性,而这个this是默认是作为函数值返回的。
然后,与工厂模式一样,构造函数方式也是没创建一个对象,就生成一个新函数。
3、原型方式
原型方式利用了对象的prototype属性。在object类中,每个对象都有一个prototype属性,该属性代表对象的父类。
function Person(){ }
Person.prototype.name='fanfan';
Person.prototype.say=function(){
alert('who is'+this.name);
}
var person1 = new Person();
var person2 = new Person();
当new Person()被调用时,所有的prototype的属性和方法立即被分配给创建的对象,这样所有的Person实例就都包含了指向相同say()函数的指针。从语义上讲,属性和方法都属于一个对象,这就解决了前面重复生成函数的问题。此外,在这种方式中,我们还可以使用instanceof运算符检测给定变量所指向的对象类型。
alert(person1 instanceof Person);//true
但是,原型方式不能通过构造函数传递参数初始化属性值。
4、混合构造函数和原型方式
使用构造函数方式定义对象的属性,使用原型方式定义对象的方法。这样,函数只创建一次,同时每个对象都有自己的对象属性实例。
function Person(name){
this.name=name;
}
Person.prototype.say=function(){
alert('who is'+this.name);
}
var person1 = new Person('fanfan');
var persion2 = new Person('xiaoxiao');
alert(person1.say());//fanfan
alert(person1.say());//xiaoxiao
5、动态原型方式
function Person(name){
this.name=name;
if(typeof Person.initial == 'undefined'){
Person.prototype.say=function(){
alert('who is'+this.name);
}
Person.initial = true;
} }
var person1 = new Person('fanfan');
var persion2 = new Person('xiaoxiao');
alert(person1.say());//fanfan
alert(person1.say());//xiaoxiao
6、使用JSON格式创建对象
var personobj={
firstname:'fanfan',
lastname:'xiaoxiao',
age:50,
tellyourage:function{ alert('yourage:'+this.age)
}
}
与工厂方式没有本质区别,只是更加快捷。
三、对象继承实现
创建子类将继承超类的所有属性和方法,包括构造函数及方法的实现。记住,所有属性和方法都是公用的,因此子类可直接访问这些方法。子类还可添加超类中没有的新属性和方法,也可以覆盖超类中的属性和方法。
1、对象冒充
所谓对象冒充,就是新的类冒充旧的类(旧的类必须采用构造函数的方式),从而达到继承的目的,其原理如下:构造函数使用this关键字给所有属性和方法赋值(即采用类声明的构造函数方式)。因为构造函数只是一个函数,所以 可使ClassA的构造函数成为ClassB的方法,然后调用它。ClassB就会收到ClassA的构造函数中定义的属性和方法。
function Person(name){ this.name=name;
this.say=function(){
alert('who is'+this.name);
} }
我们知道,关键字this引用的事构造函数当前创建的对象。而在方法中,this指向的是所属的对象。这个原理是把People作为常规函数来建立继承机制,而不是作为构造函数。
function WhitePeople(name){
this.inherit=People;//冒充
this.inherit(name);//继承
delete this.inherit;//删除继承
this.area = function(){
alert('我在欧洲');
}
}
var tom=new WhitePeople('tom');
tom.say();
tom.area();
所以新属性和新方法必须在删除了继承后再定义,这样是为了避免覆盖父类的相关属性和方法。
对象冒充可以支持多继承,也就是说,一个类可以继承多个超类。
function Person(name){ this.name=name;
this.say=function(){
alert('who is'+this.name);
} }
function Worker(pay,work){
this.pay=pay;
this.work=work;
} function City_worker(name,pay,work){
this.inherit = People;
this.inherit(name);
delete this.inherit; this.inherit = Work;
this.inherit(pay,work);
delete this.inherit; }
var jerry=new City_worker('jerry','10000','coder');
jerry.say();
alert(jerry.work);
2、call方式
基类.call(对象,参数列表)
function WhitePeople(name){
//this.inherit=People;//冒充
//this.inherit(name);//继承
//delete this.inherit;//删除继承
People.call(this.name);
this.area = function(){
alert('我在欧洲');
}
}
var tom=new WhitePeople('tom');
tom.say();
tom.area();
3、apply
apply()也是对象冒充一个封装函数。apply()方法有两个参数,用做this的对象和要传递给函数的参数的数组。其格式为:
基类.apply(对象,参数数组);
function City_worker(name,pay,work){
People.apply(this,new Array(name));
Worker.apply(this,[pay,work]); }
var jerry=new City_worker('jerry','10000','coder');
jerry.say();
alert(jerry.work);
4、原型链
上面三种方式都是采用构造函数的方式继承,对应的,也具有原型函数方式的继承,原型链。
function Blue_collor(){ }
Blue_collor.prototype.name='jean';
Blue_collor.prototype.say=function(){
alert('who is '+this.name);
}
function City_blue_collor(){ }
City_blue_collor.prototype = new Blue_collor();
var j1 = new City_blue_collor();
j1.say();
注意在使用原型链继承时,基类构造函数内不能有任何参数。
Javascript基础编程の面向对象编程的更多相关文章
- Java基础-初识面向对象编程(Object-Oriented-Programming)
Java基础-初识面向对象编程(Object-Oriented-Programming) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Java是一门面向对象的程序设计语言.那么什 ...
- 2018.3.5 Java语言基础与面向对象编程实践
Java语言基础与面向对象编程实践 第一章 初识Java 1.Java特点 http://www.manew.com/blog-166576-20164.html Java语言面向对象的 Java语言 ...
- 深入理解javascript中实现面向对象编程方法
介绍Javascript中面向对象编程思想之前,需要对以下几个概念有了解: 1. 浅拷贝和深拷贝:程序在运行过程中使用的变量有在栈上的变量和在堆上的变量,在对象或者变量的赋值操作过程中,大多数情况先是 ...
- Day7 - Python基础7 面向对象编程进阶
Python之路,Day7 - 面向对象编程进阶 本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个 ...
- javaScript设计模式之面向对象编程(object-oriented programming,OOP)(二)
接上一篇 面向对象编程的理解? 答:面向对象编程,就是将你的需求抽象成一个对象,然后针对这个对象分析其特征(属性)与动作(方法).这个对象我们称之为类.面向对象编程思想其中一个特点就是封装,就是把你需 ...
- javaScript设计模式之面向对象编程(object-oriented programming,OOP)(一)
面试的时候,总会被问到,你对javascript面向对象的理解? 面向对象编程(object-oriented programming,OOP)是一种程序设计范型.它讲对象作为程序的设计基本单元,讲程 ...
- 02_python基础(面向对象编程)
面向对象编程: 把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装(encapsulation)隐藏内部细节,通过继承(inheritance ...
- Python基础之面向对象编程
面向对象编程 —— Object Oriented Programming 简写 OOP 01. 面向对象基本概念 我们之前学习的编程方式就是 面向过程 的 面向过程 和 面向对象,是两种不同的 编程 ...
- ndk学习之c++语言基础复习----面向对象编程
关于面向对象编程对于一个java程序员那是再熟悉不过了,不过对于C++而言相对java还是有很多不同点的,所以全面复习一下. 类 C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程 ...
- Day6 - Python基础6 面向对象编程
Python之路,Day6 - 面向对象学习 本节内容: 面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法. 引子 你现在是一家游戏公司的开发 ...
随机推荐
- python打造XslGenerator
0x00前言 今天加载了Demon哥分享的RSS.其中有一篇是三好学生讲的: 在仔细越读这篇文章后,我懂得了里面的一些骚操作,所以有了以下的 脚本. 0x001代码 import optparse i ...
- Tkinter按钮(Button)
Python - Tkinter Button按钮组件是用来添加一个Python应用程序中的按钮.这些按钮可以显示文字或图像,表达按钮的目的.当你按一下按钮时,您可以附加到一个按钮的函数或方法,该方法 ...
- Python操作中缓存Redis
Redis redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorte ...
- 【iBatis】使用resultMap配置返回结果时报错“列名无效”
使用iBatis联查DEPT.EMP两张表时 采用如下结构 <resultMap id="find_departmentMap" class="com.dto.De ...
- 修改kvm虚拟机镜像大小
修改虚拟机镜像大小(qcow2/raw resize) 创建一个镜像文件,大小1G taw muxueqz@muxueqz /tmp $ qemu-img create -f raw t.raw 1G ...
- 并发编程之IO模型比较和Selectors模块
主要内容: 一.IO模型比较分析 二.selectors模块 1️⃣ IO模型比较分析 1.前情回顾: 上一小节中,我们已经分别介绍过了IO模型的四个模块,那么我想大多数都会和我一样好奇, 阻塞IO和 ...
- 简单HttpClientUtils工具类
package com.zy.utils; import org.apache.http.HttpEntity; import org.apache.http.HttpStatus; import o ...
- 114. Flatten Binary Tree to Linked List (Stack, Tree; DFS)
Given a binary tree, flatten it to a linked list in-place. For example, Given 1 / \ 2 5 / \ \ 3 4 6 ...
- jquery入门 动态调整div大小,使其宽度始终为浏览器宽度
有时候我们需要设置宽度为整个浏览器宽度的div,当然我们可以使用相对布局的方式做到这一点,不过我们也可以用jquery来实现. <!doctype html> <html> & ...
- Mask_rcnn openpose realsense
cd /home/luo/Desktop/MyFile/Mask_RCNN_Openpose_Realsense python realsense_mask_openpose_2019032601.p ...