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 相关文章推荐
理解Javascript_09_Function与Object
Oct 16 Javascript
基于jQuery的动态增删改查表格信息,可左键/右键提示(原创自Zjmainstay)
Jul 31 Javascript
javascript提取URL的搜索字符串中的参数(自定义函数实现)
Jan 22 Javascript
jQuery产品间断向下滚动效果核心代码
May 08 Javascript
Javascript验证方法大全
Sep 21 Javascript
JS实现获取键盘按下的按键并显示在页面上的方法
Nov 04 Javascript
Vue 固定头 固定列 点击表头可排序的表格组件
Nov 25 Javascript
JS实现的模仿QQ头像资料卡显示与隐藏效果
Apr 07 Javascript
JS中常用的消息框总结
Feb 24 Javascript
JS使用tween.js动画库实现轮播图并且有切换功能
Jul 17 Javascript
详解Vue基于vue-quill-editor富文本编辑器使用心得
Jan 03 Javascript
jQuery实现的解析本地 XML 文档操作示例
Apr 30 jQuery
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
frename PHP 灵活文件命名函数 frename
2009/09/09 PHP
PHP中使用addslashes函数转义的安全性原理分析
2014/11/03 PHP
自定义min版smarty模板引擎MinSmarty.class.php文件及用法
2016/05/20 PHP
Laravel中Facade的加载过程与原理详解
2017/09/22 PHP
javascript 学习之旅 (3)
2009/02/05 Javascript
JavaScript初学者应注意的七个细节小结
2012/01/30 Javascript
JQuery入门——事件切换之toggle()方法应用介绍
2013/02/05 Javascript
JavaScript实现的日期控件具体代码
2013/11/18 Javascript
jQuery添加/改变/移除CSS类及判断是否已经存在CSS
2014/08/20 Javascript
JavaScript函数模式详解
2014/11/07 Javascript
使用EVAL处理jqchart jquery 折线图返回数据无效的解决办法
2015/11/26 Javascript
Jquery 1.9.1源码分析系列(十二)之筛选操作
2015/12/02 Javascript
详解angular2采用自定义指令(Directive)方式加载jquery插件
2017/02/09 Javascript
es6的数字处理的方法(5个)
2017/03/16 Javascript
Javascript 一些需要注意的细节(必看篇)
2017/07/08 Javascript
react native仿微信PopupWindow效果的实例代码
2017/08/07 Javascript
vue基于mint-ui的城市选择3级联动的示例
2017/10/25 Javascript
Vue的土著指令和自定义指令实例详解
2018/02/04 Javascript
vue element table 表格请求后台排序的方法
2018/09/28 Javascript
从0到1搭建Element的后台框架的方法步骤
2019/04/10 Javascript
使用Phantomjs和Node完成网页的截屏快照的方法
2019/07/16 Javascript
Vue 图片压缩并上传至服务器功能
2020/01/15 Javascript
[02:56]《DAC最前线》之国外战队抵达上海备战亚洲邀请赛
2015/01/28 DOTA
详解用Python处理HTML转义字符的5种方式
2017/12/27 Python
pandas 对每一列数据进行标准化的方法
2018/06/09 Python
Python3.5基础之NumPy模块的使用图文与实例详解
2019/04/24 Python
opencv python 对指针仪表读数识别的两种方式
2021/01/14 Python
英国领先的办公用品供应商:Viking
2016/08/01 全球购物
德国苹果商店:MacTrade
2020/05/18 全球购物
单位在职证明范本
2014/01/09 职场文书
热门专业求职信
2014/05/24 职场文书
中国在我心中演讲稿
2014/09/13 职场文书
2014年财务工作自我评价
2014/09/23 职场文书
雷锋之歌观后感
2015/06/10 职场文书
校园开放日新闻稿
2015/07/17 职场文书
微信小程序APP的生命周期及页面的生命周期
2022/04/19 Javascript