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 相关文章推荐
网页的标准,IMG不支持onload标签怎么办
Jun 29 Javascript
jquery 学习笔记 传智博客佟老师附详细注释
Sep 12 Javascript
Prototype源码浅析 Number部分
Jan 16 Javascript
jQuery简单实现banner图片切换
Jan 02 Javascript
简单谈谈jQuery(function(){})与(function(){})(jQuery)
Dec 19 Javascript
jquery插件jquery.confirm弹出确认消息
Dec 22 Javascript
js字符串截取函数slice、substring和substr的比较
May 17 Javascript
JavaScript reduce和reduceRight详解
Oct 24 Javascript
Bootstrap整体框架之CSS12栅格系统
Dec 15 Javascript
canvas实现简易的圆环进度条效果
Feb 28 Javascript
node.js支持多用户web终端实现及安全方案
Nov 29 Javascript
JavaScript中常用的简洁高级技巧总结
Mar 10 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
Extended CHM PHP 语法手册之 DIY
2006/10/09 PHP
ajax+php实现无刷新验证手机号的实例
2017/12/22 PHP
javascript引用对象的方法代码
2007/08/13 Javascript
防止网站内容被拷贝的一些方法与优缺点好处与坏处分析
2007/11/30 Javascript
JavaScript 数组的 uniq 方法
2008/01/23 Javascript
jquery常用技巧及常用方法列表集合
2011/04/06 Javascript
jQuery UI AutoComplete 使用说明
2011/06/20 Javascript
利用ajaxfileupload插件实现文件上传无刷新的具体方法
2013/06/08 Javascript
jquery+CSS3实现淘宝移动网页菜单效果
2015/08/31 Javascript
JavaScript之DOM插入更新删除_动力节点Java学院整理
2017/07/03 Javascript
在页面中引入js的两种方法(推荐)
2017/08/29 Javascript
vue 全选与反选的实现方法(无Bug 新手看过来)
2018/02/09 Javascript
QML实现圆环颜色选择器
2019/09/25 Javascript
详解小程序云开发攻略(解决最棘手的问题)
2019/09/30 Javascript
详解JSON.stringify()的5个秘密特性
2020/05/26 Javascript
vue实现列表滚动的过渡动画
2020/06/29 Javascript
Python群发邮件实例代码
2014/01/03 Python
Python-基础-入门 简介
2014/08/09 Python
Python判断文件和文件夹是否存在的方法
2015/05/21 Python
Python单体模式的几种常见实现方法详解
2017/07/28 Python
Python爬虫之xlml解析库(全面了解)
2017/08/08 Python
python 定时修改数据库的示例代码
2018/04/08 Python
pandas数据处理基础之筛选指定行或者指定列的数据
2018/05/03 Python
Python实现的多进程拷贝文件并显示百分比功能示例
2019/04/09 Python
python批量修改xml属性的实现方式
2020/03/05 Python
解决pyPdf和pyPdf2在合并pdf时出现异常的问题
2020/04/03 Python
使用Python将Exception异常错误堆栈信息写入日志文件
2020/04/08 Python
Python HTMLTestRunner测试报告view按钮失效解决方案
2020/05/25 Python
uniapp+Html5端实现PC端适配
2020/07/15 HTML / CSS
Linux内核的同步机制是什么?主要有哪几种内核锁
2013/01/03 面试题
气象学专业个人求职信
2014/04/22 职场文书
清明节网上祭英烈活动总结
2014/04/30 职场文书
机关党员四风问题个人整改措施
2014/10/26 职场文书
党建工作整改措施
2014/10/28 职场文书
python中的mysql数据库LIKE操作符详解
2021/07/01 MySQL
ant design charts 获取后端接口数据展示
2022/05/25 Javascript