您的位置:首页 > Web前端 > JavaScript

Javascript-基础知识(3)

2015-08-02 19:45 633 查看
 1.回顾:上篇学习了 正则,函数,作用域,日期函数
 2.这篇将学习,面向对象与原型,匿名函数和闭包,BOM

 3.面向对象与原型
两种开发模式:1.函数式(过程化) 2.面向对象(oop):具有类的概念
JavaScript(ECMAScript)没有类的概念,因此他的对象也与基于类的语言中的对象有所不同。
继承是通过原型或者对象冒充的形式进行的。
1.创建对象,解决多个类似对象的创建,而使用工厂模式创建
e.g 工厂模式创建:
function createObject(name,age){
var obj=new Object();
obj.name=name;
obj.age=age;
obj.run=function(){
return this.name+this.age;
};
return obj;
}

var box1=createObject('yuan',23);
var box2=createObject('ming',243);


2.构造函数 创建对象;this 相当于obj,没有return语句,他是自动返回的!
e.g
function box(name,age){
this.name=name;
this.age=age;
this.run=function(){
return this.name+this.age;
};
}
var box1=new box('yuan',23);
var box2=new box('ming',243);


构造函数也是函数,但函数名第一个字母必须大写

必须new构造函数名,必须使用new 运算符!
3.对象冒充的方式调用: call()和apply() 的使用,上面!
e.g
var box3=new Object();
box.call(box3,'zhuo',2122);
shu(box3.run());


4.原型 (prototype)
用途:是包含可以由特点类型的所有实例共享的属性和方法。

prototype 通过调用构造函数而创建的那个对象的原对象!

如果是用原型的方式的话,地址是共享的。
e.g
//原型
function Box1(){} //构造函数体内什么都没有(实例属性和实例方法)
Box1.prototype.name='yuan';
Box1.prototype.age=12;
Box1.prototype.run=function (){
return this.name+this.age;
};
var box2=new Box1();
shu(box2.run());


isPrototypeOf() :判断一个对象实例(对象引用)是不是指向了原型对象,基本上,只要实例化了,就是指向了!
原型执行流程: 1,先查找函数实例里面的属性或方法,有,则返回 2,在查找原型中有没有属性和方法
hasOwnProperty(属性名) :判断实例中是否含有属性
in 操作符 同时可以判断 原型和实例中有没有属性 e.g console.log('name' in box)
5.原型的 字面量
e.g
function Box(){}
Box.prototype={
name:'yuan',
age:12,
run:function (){
return this.name+this.age;
}
};
var box1=new Box();
shu(box1.run());


6.内置引用类型的功能扩展:
e.g:
String.prototype.addstring=function(){
return this+'添加的字符串';
}
console.log('yuan'.addstring());
String.prototype.addstring=function(data){
return this+data;
}
console.log('yuan'.addstring(' ming'));


7.使用原型的缺点:

省掉了传参数;

引用类型第一次修改后,保持了共享。

原型里的已有的数据,不能改变。

解决方式:

1,使用组合模式:构造函数+原型模式;即保持独立的构造函数,保持共享的用原型;

2,上面的方式是分开的,而最好的方式动态的原型模式;也就是封装。

3,可以将原型封装到构造函数里。

4,寄生构造函数:工厂模式+构造函数

5,稳妥构造函数
e.g :
function Box(name,age){
this.name=name;
this.age=age;

if(typeof this.run !='function'){ //判断this.run 是否出现
Box.prototype.run=function(){
retrun this.name+this.age;
}
}
}


7.继承:原型链来实现 & 使用对象冒充继承
被继承的函数叫做超类型(父类型,基类)

继承的函数叫做子类型(子类型,派生类)
使用:父类实例化对象后,赋值给子类型的原型属性;

通过原型链继承 ,在继承的时候,如果属性一样的话,就近原则
e.g
function Box(){
return this.name='yuna';
}

function Table(){
return this.age='tbable';
}

function Desk(){
this.name='desk name';
return this.height='zhuo';
}

Table.prototype=new Box(); //Table继承Box,是Box的子类

Desk.prototype=new Table(); //通过原型链继承Table ,在继承的时候,如果属性一样的话,就近原则

var box1=new Desk();

shu(box1.name+box1.age)


使用对象冒充继承:call()来对象冒充;可以解决传参问题!

对象冒充,只能继承构造里的信息;

构造函数里的方法,放在构造里,每次都实例化,造成浪费。
组合继承(原型链继承+对象冒充继承)
原型式继承:
e.g :
//临时中转函数
function obj(o){ //o是传递的对象
function F(){} //F 构造是临时新建的对象,用来存储传递过来的对象
F.prototype=o; //将o 对象实例赋值给F构造的原型对象
return new F(); //返回这个得到传递过来的对象的对象实例
}

var box={
name:'yuan',
age:20,
arr:['ming','zhuo']
};

var box1=obj(box);
shu(box1.arr);
box1.arr.push('hpu');
shu(box1.arr);

var box2=obj(box);
shu(box2.arr); //box 引用类型的数据共享了


寄生继承:添加一个继承函数,这个寄生函数可以扩展;
    
e.g :在上面的基础上
function create(){
var f=obj(box);
f.run=function(){
return this.name;
};
return f;
}


4.匿名函数和闭包
匿名函数:没有名字的函数。

闭包是可访问一个函数作业域里变量的函数。即内部函数

闭包可以把局部变量驻留在内存中,可以避免是用全局变量。
实现:e.g :
//通过赋值执行
var box=function(){
return 'ming';
};
shu(box());

//通过自我执行
(function (){
shu('zhuo');
})();

//自我执行的传参
(function (age){
shu(age);
})(100);

//函数里放一个匿名函数
function bo(){
return function (){ //闭包
return 'yuan';
}
}
shu(bo()());
var bo1=new bo();
shu(bo1());

//通过闭包返回局部变量
function box2(){
var age=1000;
return function(){
return age;
}
}
shu(box2()());


e.g :
//循环里的匿名函数取值问题:使其自我执行
function box(){
var arr=[];
for(var i=0;i<10;i++){
arr[i]=(function(num){ //自我执行!!!!!
return num;
})(i);
}
return arr;
}
shu(box()[0]);


闭包中关于this对象 :闭包在运行时时指向window的,故闭包中的this是指向window的!
内存泄漏问题:无法注销内存中的对象!
私有化问题:
模仿块级作用域:javascript没有块级作用域的概念!
实现:()(); 包含自我执行的匿名函数,就可以实现私有作用域!当自我执行的私有作用域完毕后,就立即被销毁了!
e.g :
function box(){
//使用自我执行的匿名函数
(function(){
for(var i=0;i<10;i++){

}
})();
shu(i); //i 没有值
}


javascript没有私有属性的概念
可以通过get & set 来实现
e.g :
function box(){
var name;
this.setName=function (value){
this.name=value;
}
this.getName=function(){
return this.name;
}
}
var box1=new box();
box1.setName('yuanming');
shu(box1.getName());


私有变量和方法:也可以采用字面量的方式创建!
单例:永远只实例化一次,其实就是字面量对象声明方式!
5.BOM
BOM:浏览器模式,提供了很多对象,用于访问浏览器功能!
window对象,location对象,history对象等
1)window对象是最顶层的对象,有六大属性,这六大属性本身也是对象
2)window对象旗下的 document属性也是对象,并且document对象旗下有五大对象,也是对象。
3)window的属性和方法懂得调用:window.属性 ,window.方法()
4)如果某个浏览器独有的属性和方法,那么在其他就懒起可能不识别,就当作普通的使用
5)系统对话框:alert(); confirm();返回boolean值 prompt('内容','默认值');返回输入的内容
6)打印:print(); 搜索:find(); 状态栏:defaultStatus=''; 和 Status=''
7)新建窗口:open(); window.open() 参数:URL , 窗口的名称或者窗口的目标('_blank','_parent'),特定字符串 ; opener:可以实现子窗口控制父窗口!!!
8)窗口的大小和位置:screenLeft和screenTop 火狐不支持;window.screenX和window.screenY IE不支持;

跨浏览器支持:

var left=typeof screenLeft=='number'?window.screenLeft:window.screenX;

var top=typeof screenTop=='number'?window.screenTop:window.screenY;
9)定时器:间歇调用和超时调用
超时调用:实现:setTimeout(方法函数,毫秒数); e.g :setTimeout('shu(1)',2000);

推荐这样写:扩展性好:
setTimeout(function(){
console.log('yuan');
},1000);


clearTimeout() 取消当前的调用计划!
间歇调用:可以重复不断的去执行:实现:

setInterval(方法函数,毫秒数); e.g:
var num=1;
setInterval(function(){
num++;
console.log('yuan'+num);
},1000);


clearInterval()
使用超时调用来模拟间歇调用,使用递归调用!!!!
10)window.location 和 window.document.location当前地址
11)location.href()指向你想要去的地址 ;
location.search() 获取url 问号后面的 ;
location.assign() 实现跳转 ;
localtion.reload(true) 重新加载/参数为ture时,强制加载 ;
location.repalce('url') 不产生任何记录的调转!


12)history:历史记录

history.length 历史记录的数量;

history.back(); 前面的记录

history.forward(); 后面的记录

history.go(num); 跳到记录
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息