JS面向对象(3)之Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法


Posted in Javascript onFebruary 25, 2016

1.Object类

在JS中,Object是所有类的基类,使用Object类来创建自定义对象时,可以无需定义构造函数(constructor,prototype,hasOwnProperty(property))

var per = new Object();
per.name = 'zhangsan';
per.age = ;
alert(per.name + per.age);

我们想在程序中得到一个对象变量,只要能存储大量数据即可,这个时候,我们可以考虑使用Object类。Object类避免了对构造器的定义。 Object类下另一个常用的属性:hasOwnProperty

var per = new Object();
per.name = 'zhangsan';
per.age = ;
if per.hasOwnProperty('email'){
alert('具有email');
}else{
alert('无email');
}

2.静态属性

在有些面向对象的语言当中,可以使用static关键字定义类的静态属性或者静态方法,在JS中,可以进行模拟。

语法:

类名.属性名

类名.属性=function(){}

function Person(){
}
Person.count = ;
var p = new Person();
Person.count++;
var p = new Person();
Person.count++;
var p = new Person();
Person.count++;
alert(Person.count);

添加静态属性和静态方法:

function Person(){
Person.count++; //静态属性
Person.getCount=function(){ //静态方法
alert('当前共有' + Person.count + '个人');
}
}
Person.count = ;
var p = new Person();
var p = new Person();
var p = new Person();
Person.getCount();

3.闭包

概念:所谓闭包,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因此这些变量也是该表达式的一部分。

提出一个问题:

function display(){
var i=; 
}
display();
//在这里,想访问局部变量i

在全局中,不能访问局部变量i,因为作用域不同,而且,在display函数执行完毕后,局部变量i会被回收。 闭包的功能:“访问局部变量”和“使变量所占的内存不被释放”

//例
function fn(){
function fn(){
alert('hello');
}
return fn; //返回fn函数首地址
}
var test=fn(); //test也指向了fn函数的首地址
test();

通过例1我们知道:变量是可以指向函数的首地址的,函数也可以返回另一个函数的首地址。

//例
function fn(){
var i = ;
function fn(){
alert(i);
}
return fn; //返回fn函数首地址
}
var test=fn(); //test也指向了fn函数的首地址
test();

通过例2我们知道:使用一个拒不函数包含变量i,这样局部变量i的内存不会被回收。

//例
function fn(){
var i = ;
function fn(){
alert(i++);
}
return fn; //返回fn函数首地址
}
var test=fn(); //test也指向了fn函数的首地址
test();
test();
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 p = new Person('zhangsan',);
alert(p.name);
alert(p.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 p = new Person('zhangsan',);
p.setAge();
alert(p.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 p=new Person(); //Person内的this指向p
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 p = new Person('zhangsan',);
//speak(); 这样调用this指向window
//p.speak(); p对象没有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 p = new Person('zhangsan',);
speak.call(p);
speak.apply(p);

call和apply在执行时做了两件事:1)将函数内部this指向了第一个参数 2)调用函数

另外:还可以这样解决问题:

P1.say=speak;

P1.say();

这样解决和上面解决方法有本质上的区别:

上面的解决办法是直接调用speak函数,只不过函数内部this的指向发生改变。

下面的解决办法会为p1对象增加属性,p1对象的“体积”会变大。

举例说明:

<script>
function fn(){
this.style.color='red';
}
function fn(){
this.style.fontSize='px';
}
window.onload=function(){
document.getElementById('btn').onclick=function(){
var div = document.getElementById('div');
fn.call(div);
fn.apply(div);
};
};
</script>
<div id='div'>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();
stu.ext(new Person('xiaoqiang',));
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(,'zhagsan',);
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',);
var stu = new Student();
stu.speak();
stu.say();

以上内容给大家介绍了JS面向对象(3)之Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法,希望对大家有所帮助!

Javascript 相关文章推荐
js实现点击添加一个input节点
Dec 05 Javascript
AngularJS学习笔记之基本指令(init、repeat)
Jun 16 Javascript
基于zepto的移动端轻量级日期插件--date_picker
Mar 04 Javascript
artDialog+plupload实现多文件上传
Jul 19 Javascript
javascript 正则表达式去空行方法
Jan 24 Javascript
validationEngine 表单验证插件使用实例代码
Jun 15 Javascript
浅谈Angular4实现热加载开发旅程
Sep 08 Javascript
Node.js+jade+mongodb+mongoose实现爬虫分离入库与生成静态文件的方法
Sep 20 Javascript
js中json对象和字符串的理解及相互转化操作实现方法
Sep 22 Javascript
JavaScript实现树的遍历算法示例【广度优先与深度优先】
Oct 26 Javascript
js判断数组是否包含某个字符串变量的实例
Nov 24 Javascript
JS实现为动态创建的元素添加事件操作示例
Mar 17 Javascript
jquery zTree异步加载简单实例讲解
Feb 25 #Javascript
JavaScript代码因逗号不规范导致IE不兼容的问题
Feb 25 #Javascript
jquery插件jquery.LightBox.js实现点击放大图片并左右点击切换效果(附demo源码下载)
Feb 25 #Javascript
JQuery ztree带筛选、异步加载实例讲解
Feb 25 #Javascript
jquery ztree实现模糊搜索功能
Feb 25 #Javascript
jQuery实现从身份证号中获取出生日期和性别的方法分析
Feb 25 #Javascript
jquery实现列表上下移动功能
Feb 25 #Javascript
You might like
连接到txt文本的超链接,不直接打开而是点击后下载的处理方法
2009/07/01 PHP
简洁短小的 JavaScript IE 浏览器判定代码
2010/03/21 Javascript
使用CSS和jQuery模拟select并附提交后取得数据的代码
2013/10/18 Javascript
javascript中typeof的使用示例
2013/12/19 Javascript
JavaScript新窗口与子窗口传值详解
2014/02/11 Javascript
jQuery中toggle()函数的使用实例
2015/04/17 Javascript
jQuery解析XML文件同时动态增加js文件的方法
2015/06/01 Javascript
javascript实现的字符串与十六进制表示字符串相互转换方法
2015/07/17 Javascript
JS实现弹性漂浮效果的广告代码
2015/09/02 Javascript
js数组如何添加json数据及js数组与json的区别
2015/10/27 Javascript
JS 实现Base64编码与解码实例详解
2016/11/07 Javascript
NodeJS处理Express中异步错误
2017/03/26 NodeJs
vue2.x 父组件监听子组件事件并传回信息的方法
2017/07/17 Javascript
JavaScript callback回调函数用法实例分析
2018/05/08 Javascript
原生js实现淘宝放大镜效果
2020/10/28 Javascript
详解Vuex下Store的模块化拆分实践
2019/07/31 Javascript
基于Express框架使用POST传递Form数据
2019/08/10 Javascript
JavaScript获取当前url路径过程解析
2019/12/27 Javascript
JS实现秒杀倒计时特效
2020/01/02 Javascript
jQuery实现鼠标滑动切换图片
2020/05/27 jQuery
python机器学习之贝叶斯分类
2018/03/26 Python
Python代码块批量添加Tab缩进的方法
2018/06/25 Python
Python中的四种交换数值的方法解析
2019/11/18 Python
利用pyshp包给shapefile文件添加字段的实例
2019/12/06 Python
tensorflow通过模型文件,使用tensorboard查看其模型图Graph方式
2020/01/23 Python
基于python求两个列表的并集.交集.差集
2020/02/10 Python
Django DRF认证组件流程实现原理详解
2020/08/17 Python
很酷的HTML5电子书翻页动画特效
2016/02/25 HTML / CSS
《生命 生命》教学反思
2014/04/19 职场文书
学校标语口号大全
2015/12/26 职场文书
导游词之河北滦平金山岭长城
2019/10/16 职场文书
分析JVM源码之Thread.interrupt系统级别线程打断
2021/06/29 Java/Android
mongodb清除连接和日志的正确方法分享
2021/09/15 MongoDB
java objectUtils 使用可能会出现的问题
2022/02/28 Java/Android
【海涛dota解说】DCG联赛第一周 LGD VS DH
2022/04/01 DOTA
KVM基础命令详解
2022/04/30 Servers