JS面向对象(3) -- Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法
2016-02-25 00:24
1066 查看
相关链接:
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))
我们想在程序中得到一个对象变量,只要能存储大量数据即可,这个时候,我们可以考虑使用Object类。Object类避免了对构造器的定义。 Object类下另一个常用的属性:hasOwnProperty
2.静态属性
在有些面向对象的语言当中,可以使用static关键字定义类的静态属性或者静态方法,在JS中,可以进行模拟。
语法:
类名.属性名
类名.属性=function(){}
添加静态属性和静态方法:
3.闭包
概念:所谓闭包,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因此这些变量也是该表达式的一部分。
提出一个问题:
在全局中,不能访问局部变量i,因为作用域不同,而且,在display函数执行完毕后,局部变量i会被回收。 闭包的功能:“访问局部变量”和“使变量所占的内存不被释放”
通过例1我们知道:变量是可以指向函数的首地址的,函数也可以返回另一个函数的首地址。
通过例2我们知道:使用一个拒不函数包含变量i,这样局部变量i的内存不会被回收。
在例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 :公有
在上面这个例子中,我们想用var来表示私有成员属性,但Person构造函数执行完毕后,age会被回收,不能当做成员属性来使用。
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
使用call和apply来调用
call和apply在执行时做了两件事:1)将函数内部this指向了第一个参数 2)调用函数
另外:还可以这样解决问题:
P1.say=speak;
P1.say();
这样解决和上面解决方法有本质上的区别:
上面的解决办法是直接调用speak函数,只不过函数内部this的指向发生改变。
下面的解决办法会为p1对象增加属性,p1对象的“体积”会变大。
举例说明:
6.继承的三种实现方法
概念:在有些面向对象语言中,可以使用一个类(子类)继承另一个类(父类),子类可以拥有父类的属性和方法,这个功能可以在js中进行模拟。
三种方法:
第一种:扩展Object方法
举例说明:
第二种:使用call和apply方法
语法:
父类构造器.call(this,.......);
第三种:原型继承
语法:
子类.prototype = new 父类();
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的使用,继承的三种实现方法
- Object之超级奶爸一
- objective-c set/get方法(自定义自己的set/get方法)
- Objective-C中字符串(NSString和NSMutableString)常用的方法
- 从C/C++到Objective-C(二)--- 面向对象
- [iOS]Objective-C编程规范
- 【JSON异常系列】new JSONObject对象时卡死原因
- Anaconda下import caffe出现错误TypeError: 'module' object is not callable
- Objective-C 内存管理之 _ARC
- Animation动画详解(七)——ObjectAnimator基本使用
- iOS UIView动画详解(Objective-C)
- Retrofit2.0 使用归纳和 JSONObject Conveter
- Java IO之对象的序列化、ObjectInputStream和ObjectOutputStream类
- iOS NSUserDefaults setObject forKey,本地化存储,删除字典中的null,空值,本地化的时候,如果value为空值所引起的崩溃
- Swift 与 Objective-C混合编程
- TypeError: ObjectId('') is not JSON serializable
- JSONObject_v3
- Java基础(二):Object、Class、克隆、异常编程
- objective_C 优缺点
- 目标检测“Object Detection Using Generalization and Efficiency Balanced Co-occurrence Features”