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 相关文章推荐
setInterval,setTimeout与jquery混用的问题
Apr 08 Javascript
js动态设置鼠标事件示例代码
Oct 30 Javascript
JavaScript中创建字典对象(dictionary)实例
Mar 31 Javascript
jquery实现的代替传统checkbox样式插件
Jun 19 Javascript
深入探讨前端框架react
Dec 09 Javascript
AngularJS 指令详细介绍
Jul 27 Javascript
vue实现app页面切换动画效果实例
May 23 Javascript
浅谈Vue 初始化性能优化
Aug 31 Javascript
在NPM发布自己造的轮子的方法步骤
Mar 09 Javascript
微信小程序点餐系统开发常见问题汇总
Aug 06 Javascript
vue实现select下拉显示隐藏功能
Sep 30 Javascript
vue-cli或vue项目利用HBuilder打包成移动端app操作
Jul 29 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
Thinkphp调用Image类生成缩略图的方法
2015/03/07 PHP
php使用COPY函数更新配置文件的方法
2015/06/18 PHP
php实现的操作excel类详解
2016/01/15 PHP
读JavaScript DOM编程艺术笔记
2011/11/15 Javascript
JavaScript闭包实例讲解
2014/04/22 Javascript
js表头排序实现方法
2015/01/16 Javascript
Node.js开发者必须了解的4个JS要点
2016/02/21 Javascript
JSP防止网页刷新重复提交数据的几种方法
2016/11/19 Javascript
Vue组件实例间的直接访问实现代码
2017/08/20 Javascript
Vue中在新窗口打开页面及Vue-router的使用
2018/06/13 Javascript
模块化react-router配置方法详解
2019/06/03 Javascript
Webpack中loader打包各种文件的方法实例
2019/09/03 Javascript
[04:02]2014DOTA2国际邀请赛 BBC每日综述中国战队将再度登顶
2014/07/21 DOTA
Python数据结构与算法之图的最短路径(Dijkstra算法)完整实例
2017/12/12 Python
详解python while 函数及while和for的区别
2018/09/07 Python
Linux下Python安装完成后使用pip命令的详细教程
2018/11/22 Python
python将字典列表导出为Excel文件的方法
2019/09/02 Python
Pyecharts绘制全球流向图的示例代码
2020/01/08 Python
TensorFlow通过文件名/文件夹名获取标签,并加入队列的实现
2020/02/17 Python
屏蔽Django admin界面添加按钮的操作
2020/03/11 Python
Python进程间通信multiprocess代码实例
2020/03/18 Python
Django模板获取field的verbose_name实例
2020/05/19 Python
python爬虫---requests库的用法详解
2020/09/28 Python
python爬虫scrapy基于CrawlSpider类的全站数据爬取示例解析
2021/02/20 Python
澳大利亚牛仔裤商店:Just Jeans
2016/10/13 全球购物
Scholastic父母商店:儿童书籍
2017/01/01 全球购物
美国最大的香水出口:FragranceX.com
2017/11/04 全球购物
Melissa鞋马来西亚官方网站:MDreams马来西亚
2018/04/05 全球购物
艺术系大学生毕业个人自我评价
2013/09/19 职场文书
展会邀请函范文
2014/01/26 职场文书
物业保安员岗位职责制度
2014/01/30 职场文书
四年大学自我鉴定
2014/02/17 职场文书
合作投资意向书
2014/04/01 职场文书
电子信息工程自荐信
2014/05/26 职场文书
MATLAB 如何求取离散点的曲率最大值
2021/04/16 Python
vue实现登陆页面开发实践
2022/05/30 Vue.js