笔记来自慕课网的js和《JavaScript DOM编程艺术》一书以及《JavaScript权威指南》一书的学习。
js基本概念
- 给网页增加交互性的脚本语言
- 简单易学易用
- 常用来给HTML网页添加动态功能,比如响应用户的各种操作
- 可以弥补HTML语言的缺陷,实现web页面客户端的动态效果
- 动态的改变网页内容
- 动态改变网页的外观
- 验证表单数据
- 响应事件
-
几乎所有浏览器都支持JavaScript
-
JavaScript的特点之一:脚本语言JavaScript只需要经过编写、运行这两个步骤,不需要编译、链接。
js代码的位置
- <script src="script.js">js代码</script>放在<head></head>标签中;
- <script src="script.js">js代码</script>放在body中;
- 将js代码写在一个单独的js文件中,在<head>中引用:
tip:在JS文件中,不需要<script>标签,直接编写JavaScript代码就可以了。
eg:
<head>
<script src="script.js"></script>
</head>
最好的做法是把<script>标签放到HTML文档的最后,</body>标签之前。
js注释
- 单行注释,在注释内容前加符号 “//”。
- 多行注释以"/"开始,以"/"结束。
js变量
- 从编程角度讲,变量是用于存储某种/某些数值的存储器。
- 定义变量使用关键字var,语法如下:
var 变量名
变量名可以任意取名,但要遵循命名规则:
1.变量必须使用字母、下划线()或者美元符($)开始。
2.然后可以使用任意多个英文字母、数字、下划线()或者美元符($)组成。
3.不能使用JavaScript关键词与JavaScript保留字。
tip:
变量最好先声明再赋值(JavaScript是一种弱类型的语言,变量可以不用先声明,但是最好先声明,比较规范),如下:
var mychar;
mychar="javascript";
如果未在var声明语句中给变量指定初始值,那么虽然声明了这个变量,但在给它存入一个值之前,它的初始值就是undefined。
- 变量的作用域
- 全局变量拥有全局作用域,在js代码中的任何地方都是有定义的。
- 函数内声明的变量是局部变量,只在函数体内有定义。
- 函数参数也是局部变量,它们只在函数体内有定义。
- 在函数体内,局部变量的优先级高于同名的全局变量。
eg:
var scope = "global";//声明一个全局变量
function checkscope(){
var scope = "local";//声明一个同名的局部变量
return scope; //返回局部变量的值,而不是全局变量的值
}
checkscope(); //结果为“local”
eg:
scope = "global";//声明一个全局变量,甚至不用var声明
function checkscopes2() {
scope = "local"; //这种做法将修改全局变量的值
return scope;
}
checkscopes2();//结果为“local”
eg:
var scope = "global scope";
function checkscope() {
var scope = "local scope";
function nested() {
var scope = "nested scope";
return scope;
}
return nested();
}
checkscope();//结果是什么呢? "nested scope"
- 函数作用域和声明提前
块级作用域:类似C语言的编程中,变量在声明它的这段花括号内是可见的,花括号外是不可见的。
函数作用域:js使用函数作用域,变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。
eg:
function test(o) {
var i = 0;//i在整个函数体内均是有定义的
if (typeof o == "object") {
var j = 0;//j在函数体内是有定义的,不仅仅是if这个代码段内
for (var k=0; k < 10; k++) {//k在函数体内是有定义的,不仅仅是在循环内
console.log(k);//输出数字0-9
}
console.log(k);//k已经定义了,输出10
}
console.log(j);//j已经定义了,但可能没有初始化
}
test("haha");//例如,“haha”是一个字符串,不是对象,所以IF判断为假,不进行if里面的代码,但是虽然j是在if内声明的,但它在整一个test函数内都是可见的,即j已经声明,仅仅未赋值,所以输出undefined。
Paste_Image.png
eg2:
var testObject = {
x:2,y:3
}
function test(o) {
var i = 0;
if (typeof o == "object") {
var j = 0;
for (var k=0; k < 10; k++) {
console.log(k);
}
console.log(k);
}
console.log(j);
}
test(testObject);//此处testObject是一个对象,满足if的判断条件,执行if花括号内的语句,j则在if花括号内赋值为0,因此j输出的值为0
Paste_Image.png
js的函数作用域是指在函数内声明的所有变量在函数体内始终可见的,这意味着变量在声明之前甚至已经可用。js的这个特性被非正式地称为声明提前,即js函数里声明的所有变量,都被提前至函数体的顶部,是在js引擎的“预编译”时进行的,是在代码开始运行之前。
eg:
var scope = "global";
function f() {
console.log(scope);//输出“undefined”,而不是“global”
var scope = "local";//变量在这里赋初始值,但变量本身在函数体内任何地方均是有定义的
console.log(scope);//输出“local”
}
f();
Paste_Image.png
解析:
第一句声明了一个全局变量,然后调用函数f(),函数f()中的第一句console.log(scope),输出的不是全局变量的scope(“global”),因为f函数中的第二句声明了局部变量的 scope,虽然这句声明在第二行,但是声明会提前到函数的开始,所以f函数中第一句的scope是局部变量的scope,而不是f函数外的scope,所以输出的是undefined,因为虽然声明提前了,但是赋值还是在后面,所以第二个console.log(scope)输出的是“local”
即,以上的代码可以等效为:
var scope = "global";
function f() {
var scope;
console.log(scope);
scope = "local";
console.log(scope);
}
f();
即<strong>函数体内的变量声明提前,而赋值不会提前,赋值在赋值语句所在位置才进行。</strong>
数据类型
字符串
- 如果字符串包含双引号,就把整个字符串放在单引号里;
- 如果字符串包含单引号,就把整个字符串放在双引号里;
- 转义字符:用反斜杠
eg:var mood ='don't ask';
数值
JavaScript允许使用带小数点的数值,并且允许任意位小数。
eg: var age =20;
var temperature = -20.33333;
布尔值
布尔数据只有两个可选值:true或false。
eg:var sleeping =true;(注意true不用加双引号)
数组
-
创建数组
-
声明:
var team = Array(4); //声明的同时说明数组的长度
var team = Array(); //只声明数组; -
数组元素赋值:
team[0]="Jane";
team[1]="John";
team[2]="Linda";
team[3]="Alin"; -
声明同时赋值:
var team=Array("Jane","John","Linda","Alin");
或者
var team=["Jane","John","Linda","Alin"]; -
数组中的元素可以是不同类型,也可以包含其他数组:
eg:
var lennon=["Jane",1995,false];
var lennon=["Jane",1995,false];
var team=[];
team[0]=lennon;
对象
- js的基本数据类型之一
- 是一种复合值,将很多值聚合在一起,也可看做是属性(名/值对)的无序集合。
- 创建对象:
- 名/值对中间用冒号分隔;
- 名/值对之间用逗号分隔;
- 属性名可以是js标识符也可以是字符串直接量;
- 保留字作为属性名要用引号括起来;
- 属性的值可以是任意类型的表达式;
- 全部名/值对用一个花括号括起来。
eg:
var empty = {};//没有任何属性的对象
var point = { x:0, y:0 };//两个属性,一个属性名是x,属性值是0;另一个属性名是y,属性值是0.
var point2 = { x:point.x, y:point.y+1 };//更复杂的值
var book = {
"main title": "javascript",//属性名里有空格,必须用字符串表示
'sub-title': "the definitive guide",//属性名里有连字符,必须用字符串表示
"for": "all audiences",//"for"是保留字,因此必须用引号
author: { //这个属性的值时一个对象
firstname: "david",//注意:这里的属性名都没有引号
surname: "flanagan"
}
};
eg:通过new创建对象
var o = new Object();
var a = new Array();
var d = new Date();
var r = new RegExp("js");
- 原型对象
- 通过js代码Object.prototype获得对原型对象的引用
- 通过new关键字和构造函数调用创建的对象的原型就是构造函数的prototype属性的值
eg:
//定义一个构造函数以初始化一个新的Point对象
function Point(x,y) {//构造函数均以大写字母开始
this.x = x;
this.y = y;
}
var p = new Point(1,1);//使用new关键字和构造函数来创建一个实例
var p2 = new Point(2,2);
Point.prototype.r = function() {//Point.prototype是Point对象的原型对象,每一个实例化的Point对象都继承这个原型对象的方法,因此才此处写原型对象的某个方法后,每一个实例化的Point对象都继承了这个方法并且可以调用
return Math.sqrt(this.x*this.x+this.y*this.y);
}
p.r();
p2.r();
- new Object()创建的对象继承自Object.prototype
- new Array() 创建的对象的原型是Array.prototype
- new Date()创建的对象的原型就是Date.prototype
- Object.create()创建一个新对象,第一个参数是这个对象的原型,第二个参数可选,用以对对象的属性进行进一步描述。这是一个静态函数,不是用来调用的。使用方法:传入所需的原型对象,则创建的 新对象继承了传进去的这个原型对象的属性。
eg:
var o1 = Object.create({x:1,y:2});//o1继承了属性x和y
var o2 = Object.create(Object.prototype);//创建了一个普通的空对象,和{}和new Object()一样
任意对象都可以被继承,即可以将任意一个对象当成原型,然后用这个原型创建一个新对象,则这个新对象继承了那个原型的属性。
eg:
function inherit(p) {//这整一个inherit函数返回了一个新的对象,它的原型对象是传入的参数p,继承了p的属性
if (p == null) throw TypeError();//p可以是一个对象但不可以是null
if (Object.create)//判断是否存在Object.create()
return Object.create(p);//存在,直接使用Object.create();
var t = typeof p;//否则进一步检测p的类型
if(t !== "object" && t !== "function") throw TypeError();//不是对象或者函数就不行
function f() {};//定义一个空的构造函数;
f.prototype = p;//设置其原型对象为p
return new f();//使用f()创建p的继承对象
}
var o3 = inherit({x:1,y:2});//o3是一个实例化的对象,它的原型对象是{x:1,y:2},继承了它的属性
- 获得属性值和设置属性值
- 获得属性:用xxx.yyy或者xxx["yyy"];
- 属性访问错误:如果这个属性不存在,则返回“undefined”;
eg:
var book = {
"main title": "javascript",
'sub-title': "the definitive guide",
author: {
firstname: "david",
surname: "flanagan"
}
};
var title = book["main title"];//得到book的“main title”属性
var subtitle = book.subtitle;//=>undefined,属性不存在
var author = book.author;//得到book的”author“属性,是一个对象
var name = book.author.surname;//得到book的”author“属性的surname属性,也可以var name = author.surname;,因为前面已经把 book.author赋给author这个变量了
var len = book.subtitle.length;//book.subtitle是undefined,没有length,所以抛出一个类型错误异常
//避免获取属性时出错的方法:
//一种冗余的但很易懂的方法:
var len = undefined;
if (book) {
if (book.subtitle) len = book.subtitle.length;
}
//一种简练的方法
var len = book && book.subtitle && book.subtitle.length;//由三个&&运算符连接起来的表达式,
//从左起,第一个若不是真值,则不用继续看后面,表达式返回第一个操作数的值;如果第一个真,
//则继续看第二个,若第二个不是真值,就返回第二个操作数的值;如果第二个也为真,
//则继续看第三个,如果第三个为假,则返回第三个的值,如果第三个为真,则返回第三个的值;
//此处,第一个操作数book为真值,是一个对象,所以继续看第二个操作数,
//第二个由于book不存在subtitle属性,所以第二个操作数是undefined,为假值,
//所以不用继续看第三个的值,表达式的值为第二个操作数的值,即undefined。
补充:即使上例存在subtitle属性,上面那个表达式最后返回的值即len的值也是undefined,因为object对象不存在length属性。要获得object对象中的length,可用如下方法:
eg:
var a = {a:1,b:2,c:3,d:4};
Object.prototype.length = function() {
var count = 0;
for(var i in this){
count ++;
}
return count;
};
alert(a.length()); //5,不是4,因为每个对象都有一个内部属性(__proto__指向原型)。
tip:xxx.yyy,点运算符后面的yyy不能是保留字或关键字,比如不能是xxx.for或xxx.class,如果属性名是保留字,必须用方括号的形式访问,比如xxx["for"],xxx["class"]
- 设置属性
eg:
book.edition = 6;//给book创建一个名为“edition”的属性
book["main title"] = "ECMAScript";//给“main title”属性重新赋值
- 继承
假设要查询对象o的属性x,如果o中不存在x,那么将会继续在o的原型对象中查询属性x.如果原型对象中也没有x,但这个原型对象也有原型,那么继续在这个原型对象的原型上执行查询,直到找到x或者查找到一个原型是null的对象为止。
eg:
function inherit(p) {
if (p == null) throw TypeError();
if (Object.create)
return Object.create(p);
var t = typeof p;
if(t !== "object" && t !== "function") throw TypeError();
function f() {};
f.prototype = p;
return new f();
}
var o = {};//o从Object.prototype继承对象的方法
o.x = 1;//给o定义一个属性x并赋值为1
var p = inherit(o);//p继承o和Object.prototype
p.y = 2;//给p定义一个属性y并赋值为2
var q = inherit(p);//q继承p、o和Object.prototype
q.z = 3;//给q定义一个属性z并赋值为3
var s = q.toString();//toString()继承自Object.prototype
console.log(q.x + q.y);//=>3:x和y分别继承自o和p
q.x = 3;//修改q的属性x的值为3
console.log(q.x);//=>3,q的属性x的值已被修改成3
console.log(o.x);//=>1,o的属性值没有被修改
console.log(p.x);//=>1,q的属性值也没有被修改
控制台运行截图.png
给q的属性x赋值,只会改变q的属性值,而它的原型对象的属性值不会被修改,即“继承”只关乎读取属性值而不关乎设置属性值。
- 检测属性
- in运算符
eg;
var o = { x:1 };
console.log("x" in o);//true,x是o的属性
console.log("y" in o);//false:y不是o的属性
console.log("toString" in o);//true:o继承toString属性
- hasOwnProperty()方法:检测给定的名字是否是对象的自有属性,对于继承属性,返回false
eg:
var o = { x:1 };
console.log(o.hasOwnProperty("x"));//true:o有一个自有属性x
console.log(o.hasOwnProperty("y"));//false:o中不存在属性y
console.log(o.hasOwnProperty("toString"));//false:toString是继承属性
- propertyIsEnumerable():检测对象的可枚举的自有属性
eg:
function inherit(p) {
if (p == null) throw TypeError();
if (Object.create)
return Object.create(p);
var t = typeof p;
if(t !== "object" && t !== "function") throw TypeError();
function f() {};
f.prototype = p;
return new f();
}
var o = inherit({ y:2 });
o.x = 1;
console.log(o.propertyIsEnumerable("x"));//true,o有一个可枚举的自有属性x
console.log(o.propertyIsEnumerable("y"));//false:y是继承来的
console.log(Object.prototype.propertyIsEnumerable("toString"));//false,不可枚举
- 用!==直接判断是否是undefined
eg:
var o = { x:1 };
console.log(o.x !== undefined);//true,o中有属性x
console.log(o.y !== undefined);//false,o中没有属性y
console.log(o.toString !== undefined);//true,o继承了toString属性
- tip:in可以区分不存在的属性和存在但值为undefined的属性
eg:
var o = { x:undefined };//属性值被显式赋值为undefined
console.log(o.x !== undefined);//false,属性存在,但值为undefined
console.log(o.y !== undefined);//false,属性不存在
console.log("x" in o);//true,属性存在
console.log("y" in o);//false,属性不存在
delete o.x;//删除了属性x
console.log("x" in o);//false,属性不再存在
操作
算术操作符
- “+”号:
连接字符串:
eg:var message = "I am feeling"+"happy";
eg: alert("10"+20); //返回1020字符串,字符串和数值拼接是更长的字符串;
加法: alert(10+20); //返回数值30; - “++”自增:eg:year++; //等效:year=year+1;
函数
- 定义一个函数:
function 函数名(参数) {
函数体;
}
eg:
function add(a,b){
var sum=a+b;
return sum;
}
var result=add(2,5); //result的值为7;
认识DOM
文档对象模型DOM定义访问和处理HTML文档的标准方法。DOM将文档呈现为带有元素、属性和文本的树结构(节点树)。
节点
- 元素节点 eg:< body>、< p>、< ul>
- 文本节点 eg: < p>xxx< /p> ;包含文本节点“xxx";
- 属性节点eg: < p title="i am a title">xxx< /p> 中 title="i am a title"是一个属性节点。
获取元素
-
getElementById
eg:var a=document.getElementById("purchase"); //a为一个对象(object),对应着ID值为purchase的元素。 -
getElementsByTagName:返回一个对象数组,每个对象分别对应着文档里有着给定标签 的一个元素。
eg:
HTML代码:
< ul>
< li>abc< /li>
< li>def< /li>
< li>ghi< /li>
< /ul>
js代码:var a=document.getElementsByTagName("li");
//js代码:返回一个数组,每个对象分别对应着document对象中的一个列表项元素,即a是一个数组,数组中的每个对象是一个li元素;
//alert(a.length);可以获得列表项元素的个数“3”;
//可以通过for循环遍历数组中的每个对象:
for(var i=0;i<a.length;i++){
alert(typeof a[i]);//typeof可以告诉我们获得的类型(object);
} -
getElementsByClassName(html5 DOM中新增的方法):返回一个对象数组,每个对象分别对应着文档里有着给定类 的一个元素。
eg:var b=document.getElementsByClassName("red select");//b对应文档中同时拥有“red”和“select”类的元素。(如果多个元素都同时拥有这两个类,则b为一个数组仍然可以通过b.length获得数组长度和通过for循环遍历数组中的对象) -
summary:
-
一份文档就是一棵节点树;
-
节点分为不同的类型:元素节点、属性节点、文本节点;
-
getElementById将返回一个对象,该对象对应着文档里的一个特定的元素节点;
-
getElementsByTagName和getElementsByClassName将返回一个对象数组,它们分别对应着文档里的一组特定的元素节点;
-
每个节点都是一个对象。
获取和设置属性
-
getAttribute:xxx.getAttribute(属性名);
eg:
var c = document.getElementsByTagName("p");
for (var i=0;i<c.length;i++){
alert(c[i].getAttribute("title"));//弹出文档中每一个标签为p的元素的title属性的值,如果没有这个属性,则会返回null
} -
setAttribute:xxx.setAttribute(属性名,我们要设置的属性值);
eg:var d=document.getElementById("choose");
d.setAttribute("title","choose something");//为ID值为choose的元素设置title属性的属性值为“choose something”
(tip:如果为已经拥有指定属性的属性设置属性值则会改变原有的属性值。例如原来的title属性值为“哈哈”,后来设置为“choose something”,则title的属性值为“choose something”。)
tip:通过setAttribute对文档做出修改后,在通过浏览器查看源代码时看到的仍然是修改前的属性,也就是说setAttribute做出的修改不会反映在文档本身的源代码里。这种“表里不一”的现象源自DOM的工作模式:先加载文档的静态内容,再动态刷新,动态刷新不影响文档的静态内容。这正是DOM的真正威力:对页面内容进行刷新却不需要在浏览器里刷新页面。
事件处理函数
- <a href="xxx" onclick="show();return false;">click me</a>
原本点击这个链接是会跳转到相关链接去的,但是在onclick设置了return false,则链接的默认行为不会被触发,仅执行onclcik中的函数。(通过return false禁用默认行为)。
childNodes属性
xxx.childNodes; //获得xxx的全体子元素(数组)
tip:返回的数组包含所有类型的节点,不仅仅是元素节点,甚至连空格和换行都会被解释为节点。
nodeType属性
- 元素节点的nodeType属性值为1;
- 属性节点的nodeType属性值为2;
- 文本节点的nodeType属性值为3.
nodeValue属性:改变文本节点的值
eg:< p id="description">xxx< /p>
var description=document.getElementById("description");
如果直接:alert(description.nodeValue);将返回null,因为description是< p>,而< p>中的文本是< p>的第一个子节点,所以要获得< p>中的文本,则应为:alert(decription.childNodes[0].nodeValue);
firstChild和lastChild属性
xxx.firstChild等价于xxx.childNodes[0],第一个子节点;
xxx.lastChild等价于xxx.childNodes[xxx.childNodes.length-1],最后一个子节点。
分离JavaScript
例如为一个链接添加点击事件:
法一:<a href="http://www.example.com" onclick="popUp(this.getAttribute('href'));return false;">example</a>
当点击此链接文本时,将调用popUp函数,并且由于return false,a标签的默认行为(打开一个链接)将被禁用。
如果要将js代码与HTML文档分离:
法二:<a href="http://www.example.com" class="popup">example</a>
步骤:
- 把文档里的链接全放入一个数组里;
- 遍历数组;
- 如果某个链接的class属性等于popUp,就表示这个链接在被点击时应该调用popUp()函数。
window.onload=prepareLinks;
function prepareLinks(){
var links=document.getElementsByTagName("a");
for(var i=0;i<links.length;i++){
if(links[i].getAttribute("class")=="popup"){
links[i].onclick=function(){
popUp(this.getAttribute("href"));
return false;
}
}
}
}
向后兼容
对于不支持DOM的一些浏览器应有相应的处理,比如一些不支持DOM的浏览器就没有getElementById这些方法,因此先进行对象检测。
对象检测
eg:
function myFunction(){
if(document.getElementById){//检测浏览器是否支持这个方法
xxxx;//如果支持该方法,则执行这段语句,如果不支持,则永远不会执行
}
}
改进:
window.onload=function(){
if(!document.getElementsByTagName||document.getElementById)return false;//使用逻辑非和逻辑或,可以检测多种方法;如果不支持,则跳出整个函数,如果支持,继续往下执行。
xxxx;
}
性能考虑
- 尽量减少访问DOM和尽量减少标记
eg:
if(document.getElementById("haha").length>0){
for(var i=0;i<document.getElementById("haha").length;i++){
xxx;
}
}
这样子的代码重复访问了DOM树,降低了性能。
改进:
var links=document.getElementById("haha");
if(links.length>0){
for(var i=0;i<links.length;i++){
xxx;
}
}
这样仅一次搜索DOM树即可实现相同的功能。
- 合并和放置脚本
eg:
<script src="script/functionA.js></script>
<script src="script/functionB.js></script>
<script src="script/functionC.js></script>
<script src="script/functionD.js></script>
应合并成一个js文件,这样可以减少加载页面发送的请求数量,提高性能。
而且建议把<script>标签放在文档的末尾,</body>的前面,可以让页面变得更快。
- 压缩脚本:把脚本文件中不必要的字节,如空格和注释都删除。
精简后的代码失去了可读性,解决方法:把压缩前的脚本文件保存为副本,把压缩后的脚本文件命名为xxx.min.js文件放在站点上。
动态创建标记
document.write
eg:document.write("< p>This is inserted.< /p>");//插入一段文本
tip:使用document.write 不能很好地将行为与表现分开,因此应避免使用这个方法。
innerHTML
-
读:eg:
< div id="testdiv">
< p>this id < em>my< /em>content.< /p>
< /div>
js:alert(document.getElementById("testdiv").innerHTML);
结果:< p>this id < em>my< /em>content.< /p> -
写:eg:
< div id="testdiv">< /div>
js:var testdiv=document.getElementById("testdiv");
testdiv.innerHTML="< p>this id < em>my< /em>content.< /p>";
DOM方法
- createElement方法和appendChild方法
document.createElement方法创建一个新的元素节点,但是创建后的节点仍然是游离的,要把它添加到DOM节点树种。
eg:
< div id="testdiv">< /div>
var para=document.createElement("p");<!--创建了一个<p>元素节点-->
var testdiv=document.getElementById("testdiv");
testdiv.appendChild(para);<!--把创建的节点添加为div的子节点-->
- createTextNode方法
eg:
< div id="testdiv">< /div>
var para=document.createElement("p");<!--创建了一个<p>元素节点-->
var testdiv=document.getElementById("testdiv");
var txt =document.createTextNode("hello");<!--创建文本节点-->
testdiv.appendChild(para);<!--把创建的节点添加为div的子节点-->
para.appendChid(txt);<!--将文本节点添加为p元素的子节点-->
- insertBefore()方法
parentElement.insertBefore(newElement,targetElement);
新元素(newElement):你想插入的新元素
目标元素(targetElement):你想把新元素插入到哪个元素之前;
父元素(parentElement):目标元素的父元素。
eg:(要把一张图片插入到ul前面)
<body>
<ul id="gallery">
<li>xxx</li>
<li>xxx</li>
</ul>
</body>
js:
var gallery=document.getElementById("gallery");
gallery.parentNode.insertBefore(placeolder,gallery);//假设placeolder是新生成的一个图片的元素节点,则这句代码实现将placeolder插入到gallery之前
- insertAfter方法?
没有。
但是可以编写一个:
function insertAfter(newElement,targetElement){
var parent=targetElement.parentNode;//目标元素的父元素
if(parent.lastChild==targetElement){如果目标元素是最后一个元素,要把新元素插入,只要为父元素append一个子节点,自然就是在目标元素的后面了;
parent.appendChild(newElement);
}else{//如果目标元素不是最后一个元素,那么就把新元素插在目标元素和目标元素后面一个元素的之间,所以就是用insertBefore,插在targetElement.nextSibling之前;
parent.insertBefore(newElement,targetElement.nextSibling);
}
}
className属性
可读可写;
xxx.className=aClass; //aClass是一个类名。
tip: 这样写是替换某个元素的class属性,原来有的class属性将被覆盖,如果原来没有class属性,则为添加class属性。
如果只是想要增加一个class而不替换原来的class,就要:
xxx.className+=" info"; //注意:info是一个要新增加的类,前面要有一个空格,表示将原来的类名和新的类名用空格连接起来,所以就不会把原来的类替换掉。
可以先判断原来是否已经有类,即检查className属性的值是否为null;
如果是,即原来没有类,就把新的class设置值直接赋值给className属性;
如果不是,即原来已经存在类,就把一个空格和新的class设置值追加到className属性上去。
封装成一个函数:
function addClass(element,value){//element是需要添加类的元素,value是要添加的类名
if(!element.className){//如果element的className值为null,即原来没有类
element.className=value;//直接把新的类名赋值给className;
}
else{如果element的className值不为null,即原来有类
newClassName=element.className+" value";//将新旧类连接;
element.className=newClassName;
}
}
用js实现动画效果
原理:让元素的某个属性值随时间的变化而变化。
setTimeout
xxx=setTimeout("function",interval);//function是要执行的函数,interval是以毫秒为单位设定了需要经过多长时间后才开始执行函数
eg:movement=setTimeout(“moveMessage()”,5000);//5秒之后执行moveMessage函数
- clearTimeout(xxx)//取消要执行的函数,xxx为setTimeout函数调用返回值的变量eg:clearTimeout(movement);
parseInt函数
可以把字符串里的数值信息提取出来。
parseInt("39 steps"); //返回数值39
由elem.style.left得到的值比如为50px,是字符串,就可以通过parseInt函数来获得数值进行计算。
待续。。。
网友评论