JS面向对象(3) -- Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法
相关链接:
JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式
JS面向对象(2) -- this的使用,对象之间的赋值,for...in语句,delete使用,成员方法,json对象的使用,prototype的使用,原型继承与原型链
JS面向对象(3) -- Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法
1.Object类
在JS中,Object是所有类的基类,使用Object类来创建自定义对象时,可以无需定义构造函数(constructor,prototype,hasOwnProperty(property))
- 1 var per = new Object();
- 2 per.name = 'zhangsan';
- 3 per.age = 30;
- 4 alert(per.name + per.age);
我们想在程序中得到一个对象变量,只要能存储大量数据即可,这个时候,我们可以考虑使用Object类。Object类避免了对构造器的定义。 Object类下另一个常用的属性:hasOwnProperty
- 1 var per = new Object();
- 2 per.name = 'zhangsan';
- 3 per.age = 30;
- 4 if per.hasOwnProperty('email'){
- 5 alert('具有email');
- 6 }else{
- 7 alert('无email');
- 8 }
2.静态属性
在有些面向对象的语言当中,可以使用static关键字定义类的静态属性或者静态方法,在JS中,可以进行模拟。
语法:
类名.属性名
类名.属性=function(){}
- 1 function Person(){
- 2 }
- 3 Person.count = 0;
- 4 var p1 = new Person();
- 5 Person.count++;
- 6 var p2 = new Person();
- 7 Person.count++;
- 8 var p3 = new Person();
- 9 Person.count++;
- 10 alert(Person.count);
添加静态属性和静态方法:
- 1 function Person(){
- 2 Person.count++; //静态属性
- 3 Person.getCount=function(){ //静态方法
- 4 alert('当前共有' + Person.count + '个人');
- 5 }
- 6 }
- 7 Person.count = 0;
- 8 var p1 = new Person();
- 9 var p2 = new Person();
- 10 var p3 = new Person();
- 11 Person.getCount();
3.闭包
概念:所谓闭包,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因此这些变量也是该表达式的一部分。
提出一个问题:
- 1 function display(){
- 2 var i=10;
- 3 }
- 4 display();
- 5 //在这里,想访问局部变量i
在全局中,不能访问局部变量i,因为作用域不同,而且,在display函数执行完毕后,局部变量i会被回收。 闭包的功能:“访问局部变量”和“使变量所占的内存不被释放”
- 1 //例1
- 2 function fn1(){
- 3 function fn2(){
- 4 alert('hello');
- 5 }
- 6 return fn2; //返回fn2函数首地址
- 7 }
- 8 var test=fn1(); //test也指向了fn2函数的首地址
- 9 test();
通过例1我们知道:变量是可以指向函数的首地址的,函数也可以返回另一个函数的首地址。
- 1 //例2
- 2 function fn1(){
- 3 var i = 10;
- 4 function fn2(){
- 5 alert(i);
- 6 }
- 7 return fn2; //返回fn2函数首地址
- 8 }
- 9 var test=fn1(); //test也指向了fn2函数的首地址
- 10 test();
通过例2我们知道:使用一个拒不函数包含变量i,这样局部变量i的内存不会被回收。
- 1 //例3
- 2 function fn1(){
- 3 var i = 10;
- 4 function fn2(){
- 5 alert(i++);
- 6 }
- 7 return fn2; //返回fn2函数首地址
- 8 }
- 9 var test=fn1(); //test也指向了fn2函数的首地址
- 10 test();
- 11 test();
- 12 test();
在例3中,因为i的内存永远不会被回收,所以每次调用fn2,i的值会+1。运行的结果是弹出10,弹出11,弹出12。
闭包的原理:在例3中,共有三个作用域:全局作用域,fn1的作用域,fn2的作用域。在全局作用域里有test=fn1(),其实这句话就相当于test=fn2。在fn1作用域里有 var i=10和return fn2,在fn2作用域例有alert(i++)。当全局作用域下的test=fn1()执行时,test指向了fn2的作用域,这个时候fn2作用域下的i被全局作用域钩住,根据作用域链的法则,fn2下并没有定义i,所以在fn2下的i往上一层作用域上找,找到了fn1作用域下的var i=10。所以全局的test钩住了fn2的i,fn2的i钩住了fn1的i,所以fn1运行完毕后,不会被回收。
4.私有属性
在面向对象思想中,对于有些敏感的,不想公开的成员可以定义为私有的,在JavaScript中可以模拟这个功能。
语法:
function Person(p_name){
var name = p_name;
this.age
}
var :私有
this :公有
- function Person(p_name,p_age){
- this.name = p_name;
- var age = p_age;
- }
- var p1 = new Person('zhangsan',30);
- alert(p1.name);
- alert(p1.age);
在上面这个例子中,我们想用var来表示私有成员属性,但Person构造函数执行完毕后,age会被回收,不能当做成员属性来使用。
- function Person(p_name,p_age){
- this.name = p_name;
- var age = p_age;
- this.setAge=function(a){
- age = a;
- }
- this.getAge=function(){
- return(age);
- }
- }
- var p1 = new Person('zhangsan',30);
- p1.setAge(20);
- alert(p1.getAge());
this.setAge和this.getAge两个方法使用到了局部变量age,所以age不会被回收。
如果只有set方法,说明该属性是只写属性。
如果只有get方法,说明该属性是只读属性。
5.call和apply的使用
call和apply的功能:使用指定的对象调用当前函数。call和apply的功能完全相同,只是在语法上略有不同。
语法:
call([thisObj[,arg1[,arg2[,argN]]]])
第一个参数:函数执行时,this指向谁
后面的参数:根据需要顺序指定
apply([thisObj[,argArray]])
第一个参数:函数执行时,this指向谁
第二个参数:数组,表示参数集合
在js中,函数有几种调用形式:
Person(); //Person内的this指向window
var p1=new Person(); //Person内的this指向p1
per.Person(); //Person内的this指向per
- function Person(p_name,p_age){
- this.name = p_name;
- this.age = p_age;
- }
- function speak(){
- alert(this.name + this.age);
- }
- var p1 = new Person('zhangsan',30);
- //speak(); 这样调用this指向window
- //p1.speak(); p1对象没有speak属性
使用call和apply来调用
- function Person(p_name,p_age){
- this.name = p_name;
- this.age = p_age;
- }
- function speak(){
- alert(this.name + this.age);
- }
- var p1 = new Person('zhangsan',30);
- speak.call(p1);
- speak.apply(p1);
call和apply在执行时做了两件事:1)将函数内部this指向了第一个参数 2)调用函数
另外:还可以这样解决问题:
P1.say=speak;
P1.say();
这样解决和上面解决方法有本质上的区别:
上面的解决办法是直接调用speak函数,只不过函数内部this的指向发生改变。
下面的解决办法会为p1对象增加属性,p1对象的“体积”会变大。
举例说明:
- <script>
- function fn1(){
- this.style.color='red';
- }
- function fn2(){
- this.style.fontSize='50px';
- }
- window.onload=function(){
- document.getElementById('btn').onclick=function(){
- var div1 = document.getElementById('div1');
- fn1.call(div1);
- fn2.apply(div1);
- };
- };
- </script>
- <div id='div1'>hello javascript</div>
- <input type='button' id='btn' value='确定'>
6.继承的三种实现方法
概念:在有些面向对象语言中,可以使用一个类(子类)继承另一个类(父类),子类可以拥有父类的属性和方法,这个功能可以在js中进行模拟。
三种方法:
第一种:扩展Object方法
- Object.prototype.方法=function(父类对象){
- for(var i in 父类对象){
- this[i] = 父类对象[i];
- }
- };
举例说明:
- Object.prototype.ext=function(parObject){
- //循环遍历父类对象所有属性
- for(var i in parObject){
- //为子类对象添加这个遍历到的属性
- //它的值是父类对象这个属性的属性值
- this[i] = parObject[i];
- }
- }
- function Person(p_name,p_age){
- this.name=p_name;
- this.age=p_age;
- this.speak=function(){
- alert(this.name+this.age);
- }
- }
- function Student(p_no){
- this.no=p_no;
- this.say=function(){
- alert(this.no+this.name_this.age);
- }
- }
- var stu = new Student(101);
- stu.ext(new Person('xiaoqiang',20));
- stu.speak();
- stu.say();
第二种:使用call和apply方法
语法:
父类构造器.call(this,.......);
- function Person(p_name,p_age){
- this.name=p_name;
- this.age=p_age;
- this.speak=function(){
- alert(this.name+this.age);
- }
- }
- function Student(p_no,p_name,p_age){
- this.no=p_no;
- this.say=function(){
- alert(this.name+this.age+this.no);
- }
- Person.call(this,p_name,p_age);
- }
- var stu = new Student(8,'zhagsan',18);
- stu.speak();
- stu.say();
第三种:原型继承
语法:
子类.prototype = new 父类();
- function Person(p_name,p_age){
- this.name=p_name;
- this.age=p_age;
- this.speak=function(){
- alert(this.name+this.age);
- }
- }
- function Student(p_no){
- this.no=p_no;
- this.say=function(){
- alert(this.name+this.age+this.no);
- }
- }
- Student.prototype = new Person('wangwu',21);
- var stu = new Student(10);
- stu.speak();
- stu.say();
JS面向对象(3) -- Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法的更多相关文章
- python基础-类的属性(类属性,实例属性,私有属性)
一:类的属性 类的属性分为:类属性(公有属性),实例属性和私有属性. 1)类属性(公有属性(静态字段): 类定义时直接指定的属性(不是在__init__方法中),可以通过类名直接访问属性,并且保存 ...
- day16-封装(私有静态属性、私有属性、私有方法、类方法、静态方法)
# 一: class P: __age = 30 #私有静态属性 def __init__(self,name): self.__name = name #私有属性:属性名前面加上双下划线是私有属性. ...
- 洗礼灵魂,修炼python(33)--面向对象编程(3)—特殊类方法__init__,公有属性,私有属性
在上一篇博文里,传入参数时,是在实例化对象后且在调用方法时才传入参数,感觉是不是有点繁琐对吧?可以在实例化的时候就传入参数吗?可以的,这就是本篇博文的要讲到的构造器——__init__(两边双下划线) ...
- 【python】-- 类的实例化过程、特征、共有属性和私有属性
实例化过程 1.类的定义和语法 class dog(object): #用class定义类 "dog class" #对类的说明 def __init__(self,name): ...
- Python的程序结构[0] -> 属性/Property[0] -> 类属性、实例属性和私有属性
类属性.实例属性和私有属性 Python中类的属性主要包括类属性,实例属性和私有属性,下面是对三种属性的简单介绍 类属性 / Class Property 类属性在__init__()之外初始化,在外 ...
- JavaScript面向对象(三)——继承与闭包、JS实现继承的三种方式
前 言 JRedu 在之前的两篇博客中,我们详细探讨了JavaScript OOP中的各种知识点(JS OOP基础与JS 中This指向详解 . 成员属性.静态属性.原型属性与JS原型链).今天 ...
- js面向对象(对象/类/工厂模式/构造函数/公有和原型)
https://www.cnblogs.com/sandraryan/ 什么是对象 js中一切都是对象(有行为和特征).js允许自定义对象,也提供了内建对象(string date math等) 对象 ...
- python面向对象的特点,类定义等,私有属性、公有属性、成员属性
引子:类的对象在内存中的表示def dog(name,dog_type): def bark(d): print(d,'wang wang wang ...') data = { 'name':nam ...
- JS面向对象编程创建类的方式
js创建类的方式有几种,大致如下: 1,构造函数方式: function Car(parameters) { this.name = "objectboy"; } var cat1 ...
随机推荐
- JAVA基础研究
package Test; public class L3_1 { public static void main(String[] args) { C c1=new C(100); C c2=new ...
- LINUX 根目录说明
linux目录:/bin bin是Binary的缩写.这个目录存放着最经常使用的命令./boot 这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件./data / ...
- Vue - 自定义指令
1.Vue.directive(id,definition)注册一个全局自定义指令,接收两个参数,指令ID以及定义对象 2.钩子函数:将作用域与DOM进行链接,链接函数用来创建可以操作DOM的指令 b ...
- 一些关于HTML与CSS的总结与实际应用
//学习前端也快一年了,觉得有必要好好总结一下这一年来学过的知识.一些是前辈们的精华,文章最后会讲地址一一放出,若原作者有任何介意,请及时联系我删除. 关于DOCTYPE 1.DOCTYPE的作用是什 ...
- kafka的log存储解析——topic的分区partition分段segment以及索引等
转自:http://blog.csdn.net/jewes/article/details/42970799 引言 Kafka中的Message是以topic为基本单位组织的,不同的topic之间是相 ...
- 泛型的排序问题(Collections.sort及Comparable的应用)
一.前言 java中对泛型(集合类型)排序的问题,主要采用了两张方式一种是对要排序的实体类,实现Comparable接口,另一种方式,Collections集合工具类进行排序. 二.实现Comp ...
- UVALive-4839 HDU-3686 Traffic Real Time Query System 题解
题目大意: 有一张无向连通图,问从一条边走到另一条边必定要经过的点有几个. 思路: 先用tarjan将双连通分量都并起来,剩下的再将割点独立出来,建成一棵树,之后记录每个点到根有几个割点,再用RMQ求 ...
- 做 Web 开发少不了这些的
抱歉,似乎有些标题党了.最近做服务器的热备,整理了些李纳斯工具的适用方法.看看还有不错的. 基本命令 sleep 500 暂停 ctrl + z 暂停 progress & 后台运行 jobs ...
- MVC Razor视图引擎的入门
首先我们来说说他的给我们开发者带来那些好处吧: Razor语法易于输入,易于阅读,微软当时是这样定义的:简洁,富有表现力和灵活性,支持所有文本编辑器,强大的智能提示功能,单元测试. Rozor文件类型 ...
- MongoDB和Redis-NoSQL数据库-文档型-内存型
1NoSQL简述 CAP(Consistency,Availabiity,Partitiontolerance)理论告诉我们,一个分布式系统不可能满足一致性,可用性和分区容错性这三个需求,最多只能同时 ...