JavaScript基础知识(10)
来源:互联网 发布:mac没有host 编辑:程序博客网 时间:2024/05/20 19:49
方法名后何时加圆括号?调用方法,立即执行,就加();将方法作为对象传递,不加()
闭包:函数使用了不属于自己的局部变量
闭包的问题:
1.普通方法调用完,活动对象回收。但是闭包方法导致父活动对象不释放,所以闭包方法会占用更多内存空间。
重新获得闭包,闭包内的局部变量都重置
2.闭包中多个方法,访问的是同一个局部变量。只要变量变化,所有方法都受影响。
将n放到参数里面可以实现获得一个随机的n值,但是n也属于局部变量,这种方法和之前的方法一样,都是闭包,区别就是之前的方法外界不能修改n值,而这种方法可以在首次赋值时设置n值,一般建议用这个方法
function counter(n){
function getUnique(){
return n++;
}
return getUnique;
}
var c=counter(10); //获得n的值,且仅获得一次
console.log(c());
console.log(c());
n=0;
console.log(c());
console.log(c());
c=null;
c=counter(101);
console.log(c());
要想修改闭包内的变量,只能用闭包自己的方法。
function counter(){
var n=0;
var getUnique=function(){return n++;}
var reset=function(){n=o;} //reset活动对象里面什么都没有的,没有var和参数定义,这个n不属于reset里面的
return [getUnique,reset]; //返回多个方法,可以放到数组里。方法就是对象,只要是对象都可以放到数组中
}
var funs=counter(); //获得多个方法的数组,等于var funs=[function(){return n++;},function(){n=o;}]
console.log(funs[0]()); //取出第一个方法让它立即执行
console.log(funs[0]()); //1
console.log(funs[0]()); //2
n=0;
console.log(funs[0]());
console.log(funs[0]());
funs[1](); //调出reset方法,将方法重置。reset里面的n和getUnique里面的n是同一个
c=null;
c=counter();
console.log(funs[0]());
reset里面的n=0和getUnique里面的n++都没有定义n,使用的都是同一个父级counter里面的n
function clusure(){
var arr=[];
for(var i=0;i<3;i++){ //i最后一次值是3,父级里存的是3
arr[i]=function(){return i;};
}
return arr;
}
var funs=clusure();
console.log(funs[0]()); //3 为何结果是这个?
console.log(funs[1]()); //3 为何结果是这个?
console.log(funs[2]()); //3 为何结果是这个?
实现汇率换算:
function change(){
var h1_d=5.7;
var h1_e=10;
function rbmToD(rmb){
return rmb/h1_d;
}
function rbmToE(rmb){
return rmb/h1_e;
}
return[rbmToD,rbmToE];
}
var funs=change();
console.log(funs[0](100));
console.log(funs[1](100));
自定义对象
面向过程:以任务的执行步骤为编程顺序
方法:封装并重用复杂任务的方式
问题:功能和功能操作的数据,分离
面向对象:在设计过程中,一切以描述一个对象为基本原则。
什么是对象:封装现实中一个事物的属性和功能的结构
对象中包含:属性和功能(在程序中功能就是方法)!
js中的对象:其实就是关联数组!
关联数组写法:使用key:value对,每个key之间用逗号分隔,属性名本身就是字符串
var fbb={
"姓名":"武则天",
"数学":90,
"语文":65,
"英语":91,
};
console.log("姓名:"+fbb["姓名"]);
console.log("姓名:"+fbb.姓名); //两种方法结果一样
fbb["姓名"]和fbb.姓名两种方式都可以,但是第一种方式里面要加引号的,以后推荐使用第二种方式。
js中内置对象其实有11个:
包装类型:String、Boolean、Number
所有对象的父类型:Object、Function
工具类型:Array、Date、RegExp、Math
错误类型:Error(EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError)
全局类型:Global(或者叫window)
宿主对象:由浏览器厂家自定义提供实现
分为两类:BOM对象、 DOM对象
js中创建自定义对象方式:
1.对象直接量方式:将属性名和属性值直接写出来的方式,也就是关联数组。属性名必须是字符串,但是属性名的引号可加可不加,一般不加引号的,但是要知道它是字符串。如果要在属性名中间加空格之类的,要加引号的。
在js中凡是见到大括号{},就是对象!
2.new Object方式:其实就是使用父类型Object创建对象。相当于创建一个空数组。如:
var wzt=new Object(); //相当于创建一个空数组var wzt={};
wzt.姓名="武则天"; //也可以使用wzt["姓名"]="武则天";但是不推荐按这种方式
wzt.数学=90;
console.log("姓名:"+wzt.姓名);
console.log("数学成绩:"+wzt.数学);
3. function对象模板
关联数组的length属性是失效的!!
遍历对象:
var fbb={
"姓名":"武则天",
"数学":90,
"语文":65,
"英语":91
};
function getProperties(obj){
for(var key in obj){
console.log(key+":"+obj[key]);
}
}
getProperties(fbb);
console.log(fbb.husband); //访问一个不存在的属性是不会出错的,返回的是undefined
if("husband" in fbb){
console.log(fbb.husband);
}else{
console.log("未婚");
}
如何检测对象中是否存在指定属性:
1.使用in关键字:console.log('ename' in emp1);
2.使用对象的hasOwnProperty()方法:console.log(emp1.hasOwnProperty('ename'));
3.使用undefined判断:console.log(emp1.ename===undefined);
4.在条件语句中直接判断:if(emp1.ename){console.log('ename属性存在');}
例:
方法1:
if("husband" in fbb){
console.log(fbb.husband);
}else{
console.log("未婚");
}
方法2:这种方法最常用,可以判断任意对象的属性是否存在。
if(fbb.hasOwnProperty("husband")){
console.log(fbb.husband);
}else{
console.log("未婚");
}
方法3:
if(fbb.husband!==undefined){
console.log(fbb.husband);
}else{
console.log("未婚");
}
方法4:这种做法分不清null和undefined,如果将设置husband:null;或者0等时,会返回“未婚”。判断内置对象的属性或方法时,用这种方法,通常用它判断浏览器兼容性
if(fbb.husband){
console.log(fbb.husband);
}else{
console.log("未婚");
}
在访问那些极有可能不存在的属性时,要先判断再使用。
创建自定义对象:3种
1.直接量:var obj={属性名:属性值,...}
访问属性?obj.属性名
可能不存在的属性,使用之前必须先判断存在,再使用:
判断任意对象是否包含属性:var boolean=obj.hasOwnProperty("属性名")
如果包含返回true,否则返回false
判断内置对象,浏览器对象兼容性:if(obj.属性名)--》
undefined,null,0,"",NaN都是false,其余都是true
自定义对象创建的依据?需求中的名词!就是软件要保存的数据。
需求中的动词:对象
的功能/方法
对象的属性?表,证,单,据
对象中的方法:其实指的就是对象中的功能。
如何定义:var obj={
方法名:function(){方法体}
}
方法其实就是一个对象。对象中的方法本质上就是一个特殊的属性。对象中的
方法是操作数据的功能。
对象自己的方法,如何访问自己的属性:this指代当前对象。
什么是this?是js栈中一个固定的指针,永远指向当前正在操作的对象。
//创建hmm对象,有姓名,年龄属性,还包含自我介绍功能
var hmm={
name:"Han Meimei",
age:18;
intr:function(){ //一个对象中的方法就是一个特殊的属性
//自我介绍
var str="my name is "+this.name+". I'm "+this.age+" years old";
}
};
hmm.intr(); //this指针指向hmm
操作任何元素之前,先找到他:document.getElementById();
例:
<script>
var calc={
n:undefined,
m:undefined,
add:function(){
return this.n+this.m;
},
minus:function(){
return this.n-this.m;
}
}
calc.n=parseInt(prompt("第一个数"));
calc.m=parseInt(prompt("第二个数"));
</script>
<button onclick="alert(calc.add())">加法</button>
<button onclick="alert(calc.minus())">减法</button>
面向对象的三大特点:封装、继承、多态
封装:将数据和对数据的操作,包装为一个整体,过程就叫做封装。
继承:使用现有类型,创建出新的类型。新类型中可以使用现有类型的属性和
功能!并且新类型可以扩展出现有类型没有的属性和功能。
所有对象的父类型,Object:toString()
hasOwnProperty()
都可以被使用
对象模板:又叫构造函数。专门从来反复创建相同结构的对象的专门方法。
如何定义构造函数:function 类型名(属性值参数...){
this.属性名=属性值;
......
this.方法名=function(){
方法体;
}
}
new 构造函数():
new:开空间
构造函数:划分空间结构,并且初始化内部属性的值
例:
function Student(name,age){
this.name=name;
this.age=age;
this.intr=function(){
console.log("my name is "+this.name+" I'm "+this.age+" years old");
}
this.toString=function(){
return "[name:"+this.name+",age:"+this.age+"]";
}
}
var lilei=new Student("Li Lei",19); //new是创建一个obj,Student("Li
Lei",19)调用构建函数
var hmm=new Student("Han Meimei",18);
lilei.intr();
hmm.intr();
重写方法:如果子类型认为父类型的方法不好用,可以重新定义和父类型完全
同名的方法,实现覆盖!
console.log(lilei.toString()); //得到的值都是object
console.log(hmm.toString()); //得到的值都是object
默认toString方法如果无法打印内容,默认打印的是对象类型。
一般自定义类型对象,都会重写toString方法。
this.toString=function(){
return "[name:"+this.name+",age:"+this.age+"]";
}
toString方法利用for in来更加灵活的实现:
this.toString=function(){
var str="";
for(var key in this){
if(typeof(this[key]!="function"){
str+=key+":"+this[key]+",";
}
}
return str;
}
整个案例综合如下:
function Student(name,age){
this.name=name; //分配给将来的对象的
this.age=age;
this.intr=function(){
console.log("my name is "+this.name+" I'm "+this.age+" years old");
}
this.toString=function(){
var str="";
for(var key in this){
if(typeof(this[key])!="function"){
str+=key+":"+this[key]+",";
}
}
return str;
}
}
var lilei=new Student("Li Lei",19);
var hmm=new Student("Han Meimei",18);
lilei.intr();
hmm.intr();
console.log(lilei.toString()); //得到的值都是object
console.log(hmm.toString());
hmm.birth="1990-05-30";
console.log(hmm.birth); // 1990-05-30
console.log(lilei.birth); //undefined
hmm.count=10;
lilei.count=10;
hmm.count--;
lilei.count--;
console.log(hmm.count); //9
console.log(lilei.count); //9
原型与继承:
原型:在JavaScript中,函数本身也是一个包含了方法和属性的对象。原型是
已经存在的
原型prototype:所有方法都有原型。构造函数背后,专门保存由方法创建出
的对象共有的数据。任何对象无权修改原型中的数据。
自有属性:只给一个对象定义的属性,仅属于当前对象。其他对象不能共享。
如:
hmm.birth="1990-05-30";
console.log(hmm.birth); // 1990-05-30
console.log(lilei.birth); //undefined
定义共有属性:
Student.prototype.count=10;
/*lilei.count--; //任何对象无权修改原型中的数据,如果赋值,会自动
为*/对象创建同名自有属性
Student.prototype.count--;
console.log(lilei.count);
console.log(hmm.count);
Student.prototype.count=10;
lilei.count--;
lilei.count--;
Student.prototype.count--;
console.log(lilei.count); //取自己本身的值,8 只要自己已经有的,
就不会从原型中取值
console.log(hmm.count); //取原型的值,9
共有属性:保存在原型中,由所有同类型对象共享的属性。
设置/读取:构造函数.prototype.共有属性名
不管是否创建了一个函数,只要有方法,就有原型
删除属性定义:delete方法,即可以删除自有属性,也可以删除共有属性。
语法:delete 对象[.prototype].属性; -->中括号里面可有可无
hasOwnProperty:仅检测当前对象的自有属性!
属性 in 对象:不但检测当前对象的自有属性,而且同时检测当前对象原型的
共有属性!
0 0
- JavaScript基础知识(10)
- JavaScript(一、基础知识)
- Javascript基础知识(1)
- Javascript基础知识(2)
- javascript(js)基础知识
- Javascript-基础知识(1)
- Javascript-基础知识(3)
- Javascript-基础知识(4)
- Javascript-基础知识(5)
- Javascript-基础知识(6)
- javascript基础知识(数组)
- JavaScript基础知识(一)
- JavaScript基础知识(2)
- JavaScript基础知识(3)
- javascript基础知识(一)
- JavaScript基础知识(一)
- JavaScript基础知识(2)
- javaScript基础知识(3 )
- Search Insert Position问题及解法
- gnu sort命令的--general-numeric-sort选项与--numeric-sort选项区别
- 策略模式
- 自学Android之Activity:(五)Activity启动模式
- 炫酷的ViewPager翻页动画
- JavaScript基础知识(10)
- Untiy之Android平台读写遇到的坑
- 简单工厂
- 偶尔放松一下~
- List<T> 高级进阶 实现查询功能FindAll()
- eclipse搭建ssh框架(二)
- 00003 不思议迷宫.0009.8:Bug之一
- centos 解压压缩包到指定目录
- 观察者模式