Javascript
1. 定义
基于事件和对象驱动,并具有安全性能的脚本语言。
2. 出现背景
上世纪90年代,在美国有出现,当时有上网的环境,并且有网站服务在运行。
网景公司发明了javascript语言,最初用于在客户端对表单域项目进行验证。
网景公司在1995年发布了javascript语言,起初名字为livescript,在发布的前夕该名字为javascript,与sun公司的java语言打一个擦边球,这个决定也使得网景后期得到许多商业回报。
微软公司也有自己的脚本语言,名字为Jscript(是javascript的拷贝版本)
① 在html代码里边引入js语言
<script type=”text/javascript”>具体js代码</script>
<script type=”text/javascript” src=”js文件”></script>
② 代码大小敏感
true/false
TRUE/FALSE
③ 结束符号
每个简单语句使用”;”结束,与php类似
在javascript里边,该分号不是必须,但是推荐使用
④ 注释
// 单行注释
/*多行注释*/
⑤ 变量
其值可以发生改变的量就是变量。
变量名字命名规则:
php里边:字母、数字、下划线组成,开始有$符号标志,数字不能作为开始内容
js里边:字母、数字、下划线、$符号、汉字 等5个组成部分,数字不能作为名字的开始内容。
⑥ 数据类型
php:int float string boolean array object null resource
javascript(6种): number(int/float) string boolean null undefined object
(数组是对象的一部分)
null类型:空对象类型。
var name = “”; //声明一个变量,后期要使用一个“字符串”进行赋值
var age = 0; //声明一个变量,后期要使用一个“数字”进行赋值
var obj = null; //声明一个变量,后期要使用一个“对象”进行赋值
undefined未定义类型
使用一个没有声明的变量
object对象类型:window document
各种进制数表示
十进制: var age = 23;
八进制: var score = 023; 2*8+3=19的十进制数
十六进制: var color = 0x25; 2*16+5=37的十进制数
10:A 11:B 12:C 13:D 14:E 15:F
2. 浮点数 :5.32 , .98, 0.22
2. 最大数、最小数
最大:Number.MAX_VALUE;
最小:Number.MIN_VALUE;
4. 无穷大的数
5. Number.MAX_VALUE + NUMBER.MAX_VALUE; //infinity
算术运算符:+,-,*,/,++,--
比较运算符:>,>=,<,<=,!=,==,===(比较值的大小和类型),!==
逻辑运算符:&&,||,!
注意点:
1)逻辑运算符最终结果
在php里边,最终结果是“布尔”结果
在javascript里边,&&和||是其中一个操作数,!是布尔结果
2)短路运算
只给执行一个操作数,不执行另一个操作数,不被执行的操作数就被短路。
顺序结构
分支选择结构:if elseif switch
循环结构:while() do{}while() for()
1. 条件表达式switch用法
switch(){
case 表达式:
分支;
case 表达式:
分支;
}
2. 两个关键字break和continue
break:在循环、switch里边有使用
跳出当前的本层循环
continue:在循环里边使用
跳出本次循环,进入下次循环
多个循环嵌套使用:
标志flag:
for1
red:
for2
for3
break/continue; //把for3给跳出 / 跳出本次的for3
//break 3;//php语法
break flag; //continue flag; 把标志对应的for循环给做跳出操作
break red; //continue red;
1. 什么是函数
有一定功能代码体的集合。
2. 函数的封装
2.1 传统方式
function 函数名(){}
该方式的函数有“预加载”过程,允许我们先调用函数、再声明函数
预加载:代码先把函数的声明放入内存。代码开起来是先调用、后声明,本质是先声明、后调用的。
函数名();
function 函数名(){}
函数先调用、后声明的条件是,全部代码在一个”<script>”标记里边。
变量赋值方式声明函数(匿名函数使用)
var 函数名 = function(){}
该方式没有“预加载”,必须先声明、后调用。
函数的参数
function 函数名(形参1,形参2,形参3=’abc’){}
函数名(‘tom’,23,’beijing’);//传递实参信息
实参和形参的对应关系:
没有默认值情况:
在php里边:实参的个数小于形参是不允许的
在javascript里边:实参与形参没有严格的对应关系
总结:
1. 数据类型:Number String Boolean Null Undefined Object
console.log(typeof 信息); 判断信息的数据类型
2. 运算符
算术、比较、逻辑、连接
3. 流程控制
switch
break/continue
4. 函数
封装
参数
关键字arguments:
function 函数名(){} //函数声明没有形参
函数名(实参,实参); //调用的时候有传递实参
利用arguments可以在函数里边接收实参信息。
function func(){
var len = arguments.length;
if(0 == len){
//do something
}else if(1 == len){
//do something
}else if (2 == len){
//do something
}
}
callee关键字:
意思:在函数内部使用,代表当前函数的引用。
function f1(){
xxxx具体执行代码
arguments.callee(); //调用本函数(或者f1())
//都可以使得本函数执行,我们选择callee,其可以降低代码的耦合度。
xxxx执行代码
}
f1();
耦合:一处代码的修改会导致其他代码也要发生改变。
在程序项目里边要开发低耦合度的代码。
函数返回值:
一个函数执行完毕需要返回具体的信息,使用return关键字返回信息。
在一定层度上看,全部的数据类型(数值、字符串、布尔、对象、null)信息都可以返回
return本身还可以结束函数的执行。
在函数内部返回一个函数出来。
在javascript里边,一切都是对象
在一个函数内部,可以声明数值、字符串、布尔、对象等局部变量信息,言外之意就还可以声明函数(函数内部还要嵌套函数),因为函数是对象,并且函数可以被return给返回出来。
函数调用:
传统方式函数调用
函数名();
匿名函数自调用
(function(){})();
全局变量
php里边:1.函数外部声明的变量。
2.在函数内部也可以声明全局变量(函数调用之后起作用)
funciton f1(){
global $title;
$title = “javascript”;
}
f1();
echo $title;
javascript里边:1. 在函数外部声明的变量
2. 函数内部不使用“var”声明的变量(函数调用之后起作用)
局部变量
php里边:在函数内部声明的变量
javascript里边:在函数内部声明的变量,变量前边有”var“关键字。
2. 数组声明
var arr = [元素,元素,元素。。。];
var arr = new Array(元素,元素,元素。。。);
var arr = new Array(3);
arr[0] = 元素;
arr[1] = 元素;
3. 获取数组长度
数组.length;
4. 数组遍历
沿着一定的顺序对数组内部的元素做一次切仅做一次访问,就是遍历。
for循环 遍历
for-in遍历
数组常用方法:
instanceof
push/unshift
pop/shift
indexOf/lastIndexOf
- 字符串
在javascript里边,字符串可以调用一些成员。
toUpperCase();
var content = new String("aaaa");
var content = new Array("aaddss");
接收一个字符串参数,把这个字符串作为代码,在上下文环境执行,并返回执行的结果.
eval("alert(232)");
var a = 12;
var b = 22;
console.log(eval("a+b")); //34
总结:
1. 函数
关键字:arguments/callee
返回值:return关键字
全部类型信息都可以返回
内部嵌套的函数也可以返回(对象赋值有体现)
函数调用:
传统方式
匿名函数自调用
(function(){})();
全局变量、局部变量
2. 数组使用
声明:3种方式
长度:length
遍历:for for-in
3. 字符串
字符串可以调用成员
4. eval语句
介绍
dom: document object model 文档对象模型
DOM技术:
php里边有:php语言 与 xml/html标签之间沟通的一个桥梁。
javascript里边有:js语言 与 html/xml标签之间沟通的一个桥梁。
为了方便javascript语言通过dom操作html比较方便,
把html标签的内容划分为各种节点:
文档节点(document)
元素节点
文本节点
属性节点
注释节点
dom就是学习利用javascript如何实现对html标签内容的增、删、改、查等操作
具体操作方法:
document.getElementById(id属性值);
document.getElementsByTagName(tag标签名称);
document.getElementsByName(name属性值);不推荐,有浏览器兼容问题,通常应用在form表单里边。
3. 文本节点获取
<div>hello</div>
需要借助div元素节点再获得其内部的文本节点.
var dvnode = document.getElementsByTagName(‘div’)[0];
dvnode.firstChild; //(或调用lastChild)获得元素div内部的第一个子节点对象
兄弟节点
firstChild、lastChild:父节点获得第一个/最后一个子节点
nextSibling:获得下个兄弟节点
previousSibling:获得上个兄弟节点
childNodes:父节点获得内部全部的子节点信息
以上属性在主流浏览器(火狐firefox、chrome、safari、opera)中会给考虑空白节点。在IE浏览器中不考虑。
5. 父节点
节点.parentNode;
6.属性值操作
① 获取属性值
itnode.属性名称; //只能操作w3c规定的属性
itnode.getAttribute(属性名称); //规定的 和 自定义的都可以获取
② 设置属性值
itnode.属性名称 = 值; //只能操作w3c规定的属性
itnode.setAttribute(名称,值); //规定的 和 自定义的都可以设置
属性节点获取
var attrlist = itnode.attributes; //返回对应节点内部的全部属性信息,数组列表形式返回
attrlist.属性名称; //获得具体属性节点
获得节点类型nodeType:
1------> 元素节点
2------> 属性节点
3------> 文本节点
9------> 文档节点
节点创建和追加:
节点创建
元素节点:document.createElement(tag标签名称);
文本节点:document.createTextNode(文本内容);
属性设置:node.setAttribute(名称,值);
节点追加:
父节点.appendChild(子节点);
父节点.insertBefore(newnode,oldnode); //newnode放到oldnode的前边
父节点.replaceChild(newnode,oldnode); //newnode替换到oldnode节点
节点复制操作:
被复制节点.cloneNode(true/false);
true:深层复制(本身和内部子节点都复制)
false:浅层复制(本身(包括属性)节点复制)
<div id=”apple”>hello</div>
节点删除:
父节点.removeChild(子节点);
dom对css样式操作:
<div style=”width:300px; height:200px; background-color:pink;”></div>
① 获取css样式
元素节点.style.css样式名称;
divnode.style.width; //获取宽度样式
② 设置css样式(有则修改、没有则添加)
元素节点.style.css样式名称 = 值;
divnode.style.width =‘500px’;设置div宽度样式
注意:
① dom操作css样式只能操作“行内样式”(css样式分为 行内、内部、外部)
② 操作属性样式例如background-color/border-left-color,
需要变为backgroundColor、borderLeftColor,中恒线去掉,后边首字母大写。
1.什么是事件
通过鼠标、键盘对页面所做的动作就是事件。
事件一旦发生需要有事件处理,该处理称为“事件驱动”,事件驱动通常由函数担任
onclick onmouseover onmouseout onkeyup onkeydown onblur onfocus onsubmit
2. 设置事件
2.1 dom1级方式设置
①<input type=”text” name=”username” onclick=”函数名称()” />
function 函数名称(){this[window]}
②<input type=”text” name=”username” onclick=”过程代码var a=10;var b=20;alert(123);this[itnode]” />
③itnode.onclick = function(){this[itnode]}
④itnode.onclick = 有名函数名称;
function 函数名称(){this[itnode]}
取消dom1级事件:
itnode.onclick = null;
以上是dom1级事件设置的4种具体表现形式,除了第①种(其代表window),其他三种方式的函数内部this都代表当前节点本身。
2.2 dom2级方式设置
主流浏览器方式(包括IE9以上 版本浏览器):
itnode.addEventListener(事件类型,事件处理[,事件流]); //设置
itnode.removeEventListener(事件类型,事件处理[,事件流]); //取消
IE浏览器方式(IE6/7/8):
itnode.attachEvent(事件类型,事件处理); //设置
itnode.detachEvent(事件类型,事件处理); //取消
事件类型:就是我们可以设置的具体事件,例如onclick/onmouseover等
主流浏览器方式没有”on标志”,例如addEventListener(‘click’,...);
IE浏览器方式有”on”标志
事件处理:事件驱动,可以是一个有名/匿名函数
例如addEventListener(‘click’,function(){}/有名函数);
事件流:true捕捉型、[false冒泡型]
事件取消(removeEventListener/detachEvent)操作具体要求:
① 事件处理必须是有名函数,不可以是匿名函数。
② 事件取消的参数与绑定的参数完全一致(数量/内容)
dom2级事件设置的特点:
① 可以为同一个对象设置多个同类型事件。
② 事件取消也非常灵活。
③ 对事件流也有很好的处理。
事件流:
多个彼此嵌套元素,他们拥有相同的事件,最内部元素事件被触发后,外边多个元素的同类型事件也会被触发,多个元素他们同类型事件同时执行的效果称为“事件流”
IE浏览器从开始到现在事件流始终是“冒泡型”,在IE9以后的版本支持捕捉、冒泡型。
网景的Navigator浏览器(现在火狐浏览器的许多血统来源于navigator浏览器)一开始的事件流是”捕捉型”。后期事件流有改进,针对捕捉型、冒泡型都可以支持。
事件对象
事件对象,每个事件(包括鼠标、键盘事件)触发执行的过程中,都有对应的事件对象,通过事件对象可以获得鼠标相对页面的坐标信息、通过事件对象也可以感知什么键子被 触发执行、通过事件对象还可以阻止事件流产生、阻止浏览器默认动作。
获得事件对象:
获得:
①主流浏览器(IE9以上版本浏览器):
node.onclick = function(evt){evt就是事件对象}
addEventListener(类型,function(evt){}/函数名字);
function 函数名称(evt){}
事件处理函数的第一个形参就是事件对象
② IE(6/7/8)浏览器
node.onclick = function(){window.event事件对象}
全局变量event就是事件对象
事件对象作用:
1) 获得鼠标的坐标信息
event.clientX/clientY; //相对dom区域坐标
event.pageX/pageY; //相对dom区域坐标,给考虑滚动条位置
event.screenX/screenY; //相对屏幕坐标
阻止事件流:
event.stopPropagation(); //主流浏览器
event.cancelBubble = true; // IE浏览器
冒泡型、捕捉型都可以进行阻止,为了浏览器兼容处理,只考虑冒泡型。
阻止浏览器默认动作
浏览器默认动作,注册form表单页面,提交表单的时候,浏览器的页面会根据action属性值进行跳转,这个动作称为“浏览器默认动作”。
event.preventDefault(); //主流浏览器
event.returnValue = false; //IE浏览器
return false; //dom1级事件设置起作用
4) 感知被触发键盘键子信息
event.keyCode 获得键盘对应的键值码信息
通过事件触发时候获得的keyCode数值码信息可以对应键盘的键子信息。
5. 什么是加载事件onload
js代码执行时候,需要html&css的支持,就让html先执行(先进入内存),js代码后执行
js代码在最后执行的过程就是“加载过程”,通常通过“加载事件”实现加载过程
具体设置:
<body onload=”加载函数()”>
window.onload = 匿名/有名函数; //推荐
browser object model(浏览器对象模型)
通过BOM技术可以模拟浏览器对页面进行各种操作:创建子级页面、操作历史记录页面、操作地址栏等等
4. BOM浏览器对象模型
location.href;
location.href=xxx;
(opener:调用父级页面)
变量在当前环境now、内部环境f1、内部深层环境f2/f3....都起作用的现象形成了一个链条,这个链条就称为变量的"作用域链"
外部环境变量可以给内部环境使用
作用域链的作用:
1 变量必须“先声明、后使用”
函数可以“先使用、后声明”,原因是函数有“预加载”过程(函数声明先于其他执行代码进入内存)。本质还是函数的声明在前,使用在后。
2.内部环境可以访问外部环境的变量,反之不然
3 变量的作用域是声明时决定的,而不是运行时
AO活动对象
AO: Active Object 活动对象
执行环境:
js代码执行是有环境的
该环境定义了其有权访问的其他数据
环境有一个与之关联的“活动对象AO”
环境中所有的变量和函数都是活动对象AO的属性
全局环境是最外围的执行环境,活动对象是window对象
执行环境中的代码执行完毕后就被销毁
4. 执行环境可以访问变量的类型及优先顺序
5. 重新认识全局变量和局部变量
全局变量:
声明:
① 在函数外部声明的变量
② 在函数内部不使用var声明的变量(前提是函数执行之后才起作用)
其是活动对象window的成员信息
在访问的时候,window是否设置都可以
局部变量:
声明:
在函数内部通过var声明的变量
其在一定范围内可以看做是“全局变量”。
其在本环境、内部环境、内部深层环境都可以被访问。
闭包
1. 什么是闭包
闭包就是一个函数,两个函数彼此嵌套,内部函数就是闭包
形成闭包条件是内部函数需要通过return给返回出来.
function f1(){
var age = 20;
vae height = 180;
function f2(){
console.log("age: " + age + "height: "+ height);
}
}
2. 闭包特点
闭包有权利调用其上级环境的变量信息。
3. 闭包使用规则
同一个闭包机制可以创建多个闭包函数出来,它们彼此没有联系,都是独立的。
并且每个闭包可以保存自己个性化的信息。
PHP里边,是从一个类里边获得一个具体对象。
Javascript里边,没有类的概念,可以直接创建一个对象出来,对象可以有默认成员,后期也可以给对象丰富成员出来。
① 字面量方式创建
② 构造函数创建对象
③ Object方式创建对象
//1.字面量方式创建对象
var obj1 = {};
obj1.color = "red";
obj1["height"] = 90;
obj1.run = function (){
console.log("I can running!");
}
var obj2 = {
name:"ted",
swim:function (){
console.log("I am swiming!");
}
};
//访问成员变量
console.log(obj2.name);
obj2.swim();
obj1['run']();
//2.构造函数方式创建对象
function Animal(){
this.name = "dog";
this.age = 88;
this.run = function (){
console.log("running...!");
}
}
var dog = new Animal();
console.log(dog.name);
dog.run();
//3.Object方式创建
var cat = {color:'red'};
var rabbit = new Object();
rabbit.eat = 'robbot';
console.log(rabbit); //Object{eat="robbot"}
2. 对象在内存分配
与对象有关系的内存区域:
①. 栈空间
存放的数据大小比较小,一般固定大小的信息适合存放在该空间,例如 整型、boolean、对象的引用(名称)。
②. 堆空间
该空间存储的数据比较多,空间较大,一般数据长度不固定的信息在该空间存放,例如: string、Array、对象实体
③. 数据空间
该空间存放常量、类的静态属性
④. 代码空间
存放函数体、方法体代码
3. 对象调用其他函数/对象成员
var name = "Joe";
function say(){
console.log("name: " + this.name + "speaking");
}
//window.say();
var cat = {name:"kitty",eat:'fish'};
cat.express = say;
cat.express(); //name:kitty speaking!
/*
对象调用其它函数或者方法:
解决:把其它函数增加一个别名赋予给调用对象即可
*/
var cat = {name:"tom", eat:function(){console.log(this.name+'is eating')}};
cat.eat();//cat is eating
var dog = {name:'wangwang'};
//使得dog对象调用cat的eat方法
dog.eatdd = cat.eat;
dog.eatdd();//wangwang is eating.
4. 构造函数 与 普通函数
构造函数和普通函数的区别:
没有区别,就看使用,new就是构造函数,函数()就是普通函数调用。
5. 函数的各种执行方式
① 普通函数调用
② 构造函数执行new
③ 作为对象的成员方法执行
④ 通过call和apply执行
call和apply可以明显控制变量污染的风险。
/*
call方式调用函数
好处: 无需声明新的成员出来,就可以使得对象调用其它函数或者方法.
对变量污染的风险进行了控制
*/
var cat = {name:"tom",eat:function(){console.log(this.name+" is eating!");}};
var dog = {name:"jet"};
var wolf = {name:"seven"};
//dog对象需要调用eat方法,通过call方式执行
//方法名称call(方法内部this的指针)
cat.eat.call(dog); //this 指向jet
cat.eat.call(wolf); //this指向seven
//2带参数调用
var cat = {name:"tom",eat:function(time){console.log(this.name+ time + " is eating!");}};
var dog = {name:"jet"};
var wolf = {name:"seven"};
//dog对象需要调用eat方法,通过call方式执行
//方法名称call(方法内部this的指针)
cat.eat.call(dog,"2018-09-09 20:00:00"); //this 指向jet
cat.eat.call(wolf,"2018-09-09 20:00:00"); //this指向seven
//3.
var name = "Ted";
function say(){
console.log("name: " + this.name + "speaking!");
}
//call 使得函数执行,并任意设置函数内部指针的指向
//函数.call(this指针,参数...)
say.call(cat);
6. this都是谁
① 在函数/方法里边 代表调用该函数/方法的当前对象
② 在事件中,代表元素节点对象
divnode.onclick = function(){
alert(this.value);
}
③ 代表window
④ 可以任意代表其他对象
在call和apply使用的时候,可以任意设置被执行函数内部this的代表
7. 获取构造器
构造器:使用什么元素实例化的对象,元素就称为该对象的构造器
对象.constructor; //获得构造器
//函数是一个对象,函数的构造器是"Function"
function getInfo(){
alert(123);
}
//console.log(getInfo.constructor);//Function()
//通过实例化对象的方式,创建一个对象
//function func(name,age){console.log(name+"-->"+age);}
//var funcname = new Function('name','age',"console.log(name+"-->"+age);");
var func1 = new Function('name','age',"console.log(name+"-->"+age);");
func1('Ted',33);//Ted-->33
8. return对实例化对象的影响
/*
return 的影响
仍然实例化一个对象,return后边的代码不执行
*/
function Animal(){
this.name = "hahaha";
this.age = 22;
return;
this.run = function(){
console.log("running!");
}
}
var cat = new Animal();
console.log(cat); //Animal{name="hahaha",age=22}
三大特性:封装、继承、多态
在php里边,通过给成员声明关键字体现封装。public protected private
在javascript里边,封装只体现public、private
① public公开的,在构造函数里边通过this关键字声明的成员都是公开的,函数内部、外部都可以调用
② private私有的,在构造函数里边声明局部变量,就是私有成员
//封装的特性 public(this关键字声明的成员)/private(构造函数的局部变量)
function Animal(){
//声明私有成员
var secret = "run everyday!";
var func = function(){};
//公开成员
this.leg = 4;
this.run = function(){
console.log('running!!!');
}
//对外公开的接口访问,内部可以访问私有成员
this.fight = function(){
//内部环境,可以访问外部环境的变量secret
console.log('hahha ' + secret);
}
}
var cat = new Animal();
console.log(cat.leg);
cat.run();
cat.fight();
//console.log(secret); //secret is not defined
继承特性
2.1 原型继承介绍
php里边:一个类去继承另一个类,继承类实例化对象也会拥有被继承类的成员
javascript里边:(构造)函数可以继承另外一个对象,构造函数实例化出来的对象除了本身成员外还有拥有被继承对象的成员。
原型继承关键字:prototype。
2.2 实现原型继承
函数.prototype.成员名称 = 值; //继承单一成员
函数.prototype = 对象; //继承一个对象
var cat = {color:"red",run:function(){console.log("Running!");}};
function Animal(){
this.leg = 5;
}
/*
Animal构造函数去继承cat对象
这样通过Animal实例化的对象会拥有本身的成员,也会拥有cat对象的成员
*/
Animal.prototype = cat;
var tigger = new Animal();
console.log();//{color,leg,run}
function Wolf(){
this.eye = 'slight';
}
var seven = new Wolf();
function Dog(){
this.tail = "wave";
}
Dog.prototype = seven;
var dog = new Dog();
console.log(dog);
//继承成员可以直接访问
console.log(dog.eye); //slight
//构造函数 继承单一成员
function Dog(){
this.tail = "wave";
}
Dog.prototype.color = "yellow";
Dog.prototype.hobby = function (){
console.log("Guard home!");
}
var dog = new Dog();
console.log(dog);
原型继承注意
① 对象 和 单一成员同时继承,需要先继承对象、再继承成员
② 多个对象 同时继承,最后对象起作用
③ 继承对象的成员 与 本身成员名称一致,体现本身成员结果
/*
继承prototype
1.本身和父对象拥有同名的成员变量,调用的是自身的成员
*/
var seven = {tail:"笔直的尾巴",color:"gray",act:"夜间活动"};
function Dog(){
this.tail = "摇动的尾巴";
}
Dog.prototype = seven;
var dog = new Dog();
console.log(dog);//Object {tail:"摇动的尾巴",color:"gray",act:"夜间活动"}
console.log(dog.tail); //摇动的尾巴
/*
通一个构造函数继承多个对象,后者覆盖前者
*/
var tigger = {weapon:"爪子"};
var seven = {tail:"笔直的尾巴",color:"gray",act:"夜间活动"};
function Dog(){
this.tail = "摇动的尾巴";
}
Dog.prototype = seven;
Dog.prototype = tigger;
var dog = new Dog();
console.log(dog);//Object{tail:"摇动的尾巴",weapon:"爪子"}
/*
对象和单一成员 同时继承,先对象.后单一成员
*/
var seven = {tail:"笔直的尾巴",color:"gray",act:"夜间活动"};
function Dog(){
this.tail = "摇动的尾巴";
}
Dog.prototype = seven;
Dog.prototype.run = function(){console.log("running!")}
var dog = new Dog();
console.log(dog);//Object{tail:"摇动的尾巴",color:"gray",act:"夜间活动",run...}
3. 对象访问成员的类型及顺序
//对象访问成员类型和顺序
/*
有四种: 1,2,3,4>>优先级从低到高
*/
function Wolf(){
this.eye = "闪闪发光";
this.color = ""gray; //1.对象 构造函数 继承对象 构造函数的成员
}
var seven = new Wolf();
seven.color = "red"; //2对象 构造函数 继承对象本身 成员
function Dog(){
this.tail = "摇尾巴";
this.color = "yellow"; //对象 构造函数 成员
}
Dog.prototype = seven;
var dog = new Dog();
dog.color = "white"; //对象本身成员
console.log(dog.color); //white
4.原型链
什么是原型链:
构造函数 继承 一个对象
继承对象也有构造函数,其构造函数还去继承其他对象
其他对象也有构造函数,构造函数还去继承其他对象
其他对象也有构造函数,构造函数还去继承其他对象
。。。。。
以上继承形成了一个继承的链条,称为原型链,原型链的顶端是Object
对象访问一个成员顺序:
① 对象本身获取
② 对象构造函数里边获取
③ 构造函数继承对象本身获取
④ 构造函数继承对象的构造函数里边获取
。。。。。。
直到找到Object成员为止。
例如constructor、hasOwnPrototype、isPrototypeOf等等都是原型链顶端Object的成员。
5. 对象遍历及成员属组判断
for-in
for var 成员变量 in 对象
对象[成员变量] //获得具体成员信息
/*
对象遍历和成员属性判断
for-in遍历对象
obj.hasOwnProperty(成员名称) //判断成员是否是对象成员
*/
var cat = {age:2,weapon:"牙齿"};
function Tigger(){
this.color = "yellow";
this.act = function(){
console.log("老虎吃饭");
}
}
Tigger.prototype = cat;
var tigger = new Tigger();
for(var k in north){
if (north.hasOwnProperty(k)) {
console.log("本身成员: ") +k;
}else {
console.log("非本身成员: " + k);
}
}
//结果
/*
本身成员: color,
本身成员: act,
非本身成员: age,
非本身成员: weapon,
*/
6. 原型衍生继承-复制继承
/*
继承复制使用:本质就是给对象丰富成员出来,导致问题是:如果复制对象身上
有同名的成员就会覆盖本身成员(类型编译语言的类别拓展)
复制继承的特点:
1.普通原型继承不能替代
2.可以根据需求灵活的给对象丰富成员出来
*/
var dog = {hobby:"Guard home!",eat:"boone",color:"white"};
var wolf = {tail:"笔直的尾巴",eye:"闪闪发光"};
function Animal(){
this.color = "yellow";
this.leg = 4;
}
Animal.prototype.extend = function(obj){
//遍历obj对象,把其中的成员复制出来赋予给当前对象(this);
for(var k in obj){
//被复制的成员不在当前对象this里边才复制
if (!this.hasOwnPropertyk) {
this[k] = obj[k];
}
}
}
var kitty = new Animal();
//把dog对象的成员复制一份到kitty
kitty.extend(dog);
kitty.extend(wolf);
var obj = new (Animal);
console.log(kitty);
静态成员
如果一个类里边,有这样的属性,其值不随便发生变化,全部对象都共用一个值,该属性就声明为static静态的,其在内存中无论创建多少个对象(或者其说其与具体对象无关)都只占据一份空间。
为什么使用静态成员
① 静态成员归属到类本身,可以明显的加快访问速度。
② 节省内存效果
一个类,每实例化一个对象,在堆空间都要给每个成员分配内存空间,如果有一个成员country无论创建多少个对象其的信息值也不发生变化,为了节省内存空间的使用,就把这样的成员设置为“静态成员”。其在内存中就只占据一份空间。
静态成员在php里边需要通过类名直接访问,
那么在javascript里边如果一个成员是通过函数直接调用的,就称其为“静态成员”。
//静态成员
function Cat(){
this.color = "yellow";
this.age = 5;
}
var kitty = new Cat();
/*
以上代码有两个对象,kitty,和Cat函数对象
kitty可以访问color和age成员
Cat通过如下代码可以访问addr和run成员
普通对象和函数对象 彼此不能交叉访问(联系编译型语言的类成员变量)
*/
Cat.addr = "road 1"; //静态成员
Cat.run = function (){
console.log("running!");
}
console.log(Cat.addr);//"road 1"
Cat.run();
console.log(kitty.addr); //undifined
console.log(Cat.color); //undefined
什么是异常
异常是程序运行时的一种错误。
在没有异常的时候,程序遇到“问题/错误”通常就停止运行,给用户了一种不好的体验
使用异常后,即使程序有运行错误,我们也要把这个程序完整运行完毕,以便给用户好的使用效果。
8.2具体使用异常
try{
有可能产生异常(错误)的语句
如果其中一个语句有错误,就直接跳到catch执行,后续代码就不给执行了
xxxx后续代码
}catch(Exception ex){
捕捉错误语句,通过ex对象获得具体错误信息
}finally{
在php里边没有finally
javascript和java里边有此finally
无论代码是否有错误,该处代码都给执行
}
//exception
var title = "weather";
var content = "together";
try{
console.log(title);
console.log(content);
var obj = new eval();//TypeError:eval is not a constructor
console.log(obj);
}catch(ex){
console.log(ex.message);
}finally{
console.log('hahah');
}
异常使用注意
① 并不是全部代码都放到try里边,而是有可能产生异常的代码放到try里边
② 有一定容忍度的错误可以设置异常,敏感错误不要设置
③ 最后的finally根据情况需要可以不设置
9.多态体现
多态就是多种状态。
java里边有多态,其中方法重载是多态效果之一(多个同名方法,他们的参数个数不一样)体现多态.同一个名字的方法被多次调用,由于传递的参数个数不一样,导致请求的结果也不同。
php里边
继承抽象类可以体现多态,许多类都要把继承的抽象类的方法给实现出来。不同的类实现相同的方法有自己独特的实现,他们被调用的时候呈现不同的结果
工厂设计模式可以体现多态,实例化对象调用同一个方法,由于传递的参数不同,实例化的对象也不同。
javascript体现多态
① 在函数内部可以通过arguments关键字进行多态处理,传递个数不相同的参数,通过arguments判断,进而有不同的处理。
② this关键字可以体现多态。其可以任意代表其他对象(call和apply使用)。