-----2019年5月25日
目录
1遍历对象的属性
2js中的作用域
2.1变量作用域
2.2函数作用域
2.3函数闭包
3DEBUG
4this的情况
5对象的创建
5.1工厂模式
5.2构造函数模式
5.3原型创建对象
6数组(Array)
7函数
8Date对象
9window和Global对象
10包装类
11DOM操作
for-in语句可以用于遍历对象的属性名及属性值。
for(var attribute_name in obj){
console.log(obj[attribute_name]);
}
访问对象有两种方式“.”和[],因为这里用到了变量,所以只能使用obj[attribute_name]的方法实现
注:声明但不赋值与未声明的变量都是undefined的,而使用访问未声明的变量会报错,但是访问声明的变量只会按undefined类型处理。
var a =5;
使用var关键字声明的变量,会在所有代码执行之前被声明,赋值是在改代码原来所在位置执行。
除此之外,函数创建中的声明形式也会被声明提前,也即如下代码是可以执行的,因为fun的函数被声明提前。
fun();
function fun(){
//函数体
}
解析器就是浏览器,解析器在调用函数每次都会向函数内部穿传递一个隐含参数,这个隐含的参数是this。this指向一个对象,这对象我们称之为上下文对象,根据函数的调用方式不同,this指向不同的对象
(1)以函数的形式调用。this指的永远是window,不管是在函数内部再创建函数,还是将函数返回。
function fun(){
alert(this);
function fun1(){
alert(this);
}
return fun1;
}
fun()();
运行结果
(2)以方法的形式调用。this指的是调用方法的对象。
(3)以构造函数的形式调用。this指的是新创建的那个对象
(4)使用call和apply调用时,this为指定的那个对象。
(5)事件的响应函数中,响应函数给谁绑定,this就指的谁。
封装为一个函数,传进来对象的属性值,方法体。
function CreateObj (name, age, sex) {
var obj = new Object();
obj.name = name;
obj.age = age;
obj.sex = sex;
obj.sayName = function () {
alert(this.name);
}
return obj;
}
缺点:无法区分一个对象的类型,因为这种方式创建出来的对象都是Object类型的。
构造函数与普通的函数类似,为了区别于普通函数,将构造函数的首字母大写。
构造函数的创建流程
类的概念
由于引入了构造函数,我们称使用同一个构造函数创建的对象,我们称之为一类对象,也将一个构造函数成为一个类。可以通过 instanceof 判断一个对象是否是一个类的实例。
语法:如果对象是构造函数的一个实例,返回true,否则返回false
对象名 instanceof 构造函数
缺陷:每个新的对象都会在堆区开辟一片内存空间放置变量的属性和方法,每个对象的地址是不同的,所以不同的对象也是独立。事实上有一些属性和方法是可以共用的,这些重复的属性和方法浪费了内存空间。
一种解决办法是在全局作用域创建相关的属性和函数,然后为对象赋相同的函数对象地址,从而保证所有一个类下的对象共用一个方法。但是这种方法会污染全局作用域的命名空间,而且很不安全。
每创建一个函数,解析器会向函数对象添加一个属性 prototype(原型),这个属性对应于一个对象,称为原型对象。
用图:原型对象保存着 所有通过同一构造函数创建的实例的共有属性和方法。通过原型对象可以实现方法和属性的共用。
创建方法:
使用方法:
字面量创建:var arr = [1,2,3,4,5];
使用构造函数创建:多个参数下,var arr = new Array(1,2,3,4,5);与字面量创建的效果一样,一个参数,var arr = new Array(5),表示创建一个长度为5的数组。
arr[索引值]=元素值
数组中的数据类型可以是任何类型
对于连续的数组,使用数组的length属性会返回数组长度(元素的个数),而非连续的数组,使用length返回数组最大索引值+1(故尽量不要使用非连续的数组),即空的元素也算一个位置。
大于原长度,会空出后边的元素位置,但是这些空的也是占位置的。小于原长度,多出来元素会被删除。
注:修改length后,再push元素,是从索引值为lenth的位置添加的,其前的空元素也是算一个元素。
(1)push,在数组的末尾添加一个或者多个元素,并返回新数组的长度
(2)pop,删除数组最后一个元素,并返回该元素。
(3)unshift,向数组的开头添加一个或者多个元素。并返回新数组的长度。
(4)shift,删除数组开头第一个元素,并返回删除的元素
这些方法适用于IE9+以上的浏览器,而且需要一个回调函数作为参数。
回调函数接受三个参数:element_value,element_index、array。数组中有几个参数就会执行这个回调函数几次。
(1)every。如对每一项返回ture,则返回true
(2)some。如果对任意一项返回true,则返回true
(3)forEach。对数组中每一项运行给定程序,无返回值
(4)map。对数组中的每一项运行给定的程序,有返回值
(5)filter。返回以返回true的项组成的数组。
(1)slice方法。从数组中提取指定的元素,不会影响到原来的数组。
var arr_slice = arr.slice(参数1,参数2);
参数1表示开始的元素索引,参数2表示截取的结束项的索引值(前闭后开)。
注:参数2缺省,就会一直截取到最后一个元素;
注索引值可以是负值,表示从后往前数,但是参数1一定要小于参数2,否则取得的元素是空。
(2)splice方法。从数组中删除指定元素,使用splice会影响到原数组。
arr.splice(参数1,参数2,参数3,参数4.......);
参数1表示开始位置的索引,参数2表示删除的数量,参数3及以后的参数表示要插到开始索引前边。因此splice有很多功能:
删除元素。参数3及以后参数缺省
替换元素。参数2不为空,有参数3以后的参数
插入元素。参数2为空“”(注意不是缺省)
function duplicates(arr) {
var arr_prc = [];
for(var i=0; i
(1)contact。连接两个或者多个数组
(2)join。数组转化为字符串
(3)reverse。可用于翻转数组。会影响原本数组
(4)sort。排序(默认按Unicode编码进行排序,即使是对纯数字的数组,也是这样)。会影响原本数组
如果想自定义排序的规则,可以想sort方法中传入回调函数作为参数,回调函数需要两个形参,第一个参数对应的数组元素索引一定小于第二个参数的索引。
所以,如果回调函数返回一个大于0的值,形参对应的元素在数组中交换位置;如果返回小于等于0的书,顺序都不变。
功能:当对函数调用call()和apply()时,都会执行函数内的代码。
call()函数用法:函数对象名.call(参数1,参数2,参数2......), 参数1将会成为函数执行时的this,参数2及以后的参数会作为实参传给函数。
apply()函数的用法:函数对象名.apply(参数1,参数2),参数1与call函数相同,会成为函数执行时的this,参数2是包含参数的数组,即将要传入参数的实参全部封装于一个数组当中。
用处:call和apply方法真正强大的地方是能够扩充函数赖以运行的作用域。
注意:单纯说函数应该是为window添加的方法,但是对象与函数不需要任何的耦合关系。如下的代码
myObj.sayName.call(obj);
sayName中alert的this.name指的是obj的name,而非myObj的name。注意结合第4章中的this的情况记忆。
调用函数时,浏览器都会穿给函数两个隐含参数:
注意:arguments可以用数组索引的方式访问,但是只是类数组对象,不是数组,arguments instanceOf Array返回false,Array.isArray(arguments)也返回的是false。arguments中有一个属性callee,表示当前正在执行的函数对象
var d = new Date();
直接用构造函数(缺省参数)创建的Date对象,指的当前代码执行的时间。如果在构造函数中传入“月份/日/年 时:分:秒”的字符串,d指的就是这个时间。
d.getDate(); 获取几号
d.getDay(); 获取周几
d.getMonth(); 获取几月份(返回0-11月份)
d.getFullYear(); 获取年份
类似的还有getHours,getMinutes,getSeconds
d.detTime(); 获取当前日期的时间戳(毫秒数)。
注:时间戳是只从GMT 1970年1月1日,0时0分0秒到当前日期所花的毫秒数。计算机底层在保存时间时使用的都是时间戳。
time = Date.new(); 获取当前代码执行时的时间戳
web浏览器将Global对象作为window的一部分加以实现,isNaN、isFinite、parseInt以及parseFloat实际上都是global对象的方法。
功能:将基本的数据类型转化为对象,这样可以使用对象的方式(方法和属性)对基本数据类型进行处理。因为方法和属性只能添加给对象,不能添加给基本数据类型。
但是,开发中一般不用包装类,因为会产生一些不可预料的后果。
引入包装类的原因:当我们对一些基本数据类型去访问属性、方法时,浏览器会临时使用包装类将基本数据类型转化为对象,然后调用对象的属性和方法,调用完再转化为基本数据类型。这也就是所谓的装箱拆箱。包装类可以帮助我们理解这一特性。
所以,我们可以通过基本数据的包装类的原型去设置一些方法和属性,方便装箱拆箱的时候使用。
字符串在底层是以字符数组的形式保存的。以下方法不会对源字符串产生影响,产生变化的字符串都会作为返回值返回,replace方法也不会对源字符串缠身影响。
(1)charAt。返回字符中指定位置的字符,根据索引获取字符。
(2)contact。连接两个或者多个字符串。
(3)indexOf(参数1,参数2)。检索一个字符串是否有指定的内容,从前向后找,如果有返回第一次出现的位置,如果没有返回-1,第二参数表示从哪个字符开始想后寻找。
(4)lastIndexOf(参数1,参数2)。检索一个字符串是否有指定的内容,从后向前找,如果有返回第一次出现的位置,如果没有返回-1,第二参数表示从哪个字符开始向前找。
(5)slice()。与数组的slice方法类似。
(6)subString。截取一个字符串,与slice相似,不同的是这个方法不接受负值作为参数,如果传如一个负值,则默认0,而且会自动调整参数的位置,让第一个参数小于第二个参数。
(7)split。可以将字符串拆分为一个数组。接受的参数作为拆分的标准。如果传入空串,则将每个字符转为数组元素。可以传进来一个正则表达式对象作为参数。
(8)search。搜索字符串中是否含有指定内容的索引,如果有返回第一次出现的索引,否则返回-1,可传入正则对象。
(9)replace。将查找到的内容替换为新的内容。
用法:str.replace(参数1,参数2);
参数1可以接受一个正则表达式作为参数,参数2是新的内容。默认只会替换第一个满足条件的字符串。需要删除只需要让参数2为空串“”。
注意:split未指定“g”模式,也会全局拆分;search指定“g”模式,也只会搜索第一次出现的;match和replace默认只会匹配第一个,加“g”才会匹配全局的字符串。search和indexOf的区别,search可传入正则表达式作为参数,而indexOf只能传入字符串。
DOM是API,是JavaScript为了操作HTML文档所提供的接口。document指的就是整个文档。
(1)节点
每个节点都是一个对象,共有四种节点:文档节点、元素节点、属性节点、文本节点。
(2)获取节点对象的方法
注:上边标红的节点,可能包含文本节点对象,所以如果仅仅选中元素节点的话,应避免使用。
(3)DOM增删改
语法:document.createElement("....");
用法:它需要一个标签名作为参数,并根据标签名创建元素节点对象,并将创建好的节点对象返回。
语法:document.createTextNode(".....");
用法:需要文本内容作为参数,并根据该内容创建文本节点,并将节点返回。
语法: fatherNode.apendChild(childNode);
在指定的子节点前插入新的子节点------insertBefore()
语法: fatherNode.insertBefore(newNode, oldNode);
father_node.replaceChild(new_node,old_node);
father_node.removeChild(child_node);
注意:使用innerHTML也可以完成DOM的增删改的相关操作,
var city = document.getElementById("city");
city.innerHTML +="广州 "
但我们一般情况下,我们会两中方式结合使用,推荐使用
Var city = document.getElementById("city");
var li = document.createElement("li");
li.innerHTML = "广州";
city.appendChild(li);
练习
表格+表单实现 对表格的增删操作
思路:
(1)为每个超链接都绑定一个响应事件
问题:点击超链接时,页面会跳转?
这是超连接的默认行为,此时我们不希望默认行为,可以通过响应函数的最后return false来消除默认行为.
(2)响应事件中,建立超链接和该表格一行之间的关系,从而能删除这一行.
问题1:如何获取表格的一行?
根据this的情况,事件的this是 给谁绑定,this就指的是谁. 因此可以通过this.parentNode.parentNode获取一行的元素对象tr.
问题2:为防止误操作,在删除之前应该有一个提示的文本?
类似alert的方法,应该都是window对象的方法,其中alert是警告框,confirm是确认框,prompt是提示框.其中confirm(str),用于弹出一个 str为内容的提示框,需要一个字符串为参数,该字符串会作为提示文字显示出来,而且函数会返回 如果用户点击"确定",返回true,如果用户点击"取消",返回false.
问题3:提示框应该包含用户的名字,应该通过DOM操作获取含有名字的节点?
由问题1可获取到父级的父级节点tr,如果再次使用getElementsByTagName即可获取到所有子元素.
var name = tr.getElementsByTagName("td")[0].innerHTML;
(3)添加员工.点击按钮以后,将员工的信息添加到表格中(这句话将整个业务流程给描述了,所以以下的代码都是将这句话给具体化)
注意:写代码的时候,实现什么样的功能,先在心里边想一下功能了的业务流程到底是什么样的,因为写代码就是将自己的思路用代码实现.
问题1:获取文本框中 员工的名字
首先获取文本框的对象,然后借助文本框的value的属性获取文本框内的内容
var name = document.getElementById("nameId").value;
问题2:创建四个td,一个tr对象,然后
问题3:超链接是黑色的,不能点击
向a中添加href属性
a.href = "#";
问题4:新添加的行,不能实现删除操作?
这是因为没有为新添加的超链接添加事件.为了简化代码,可以封装事件函数,因为每个删除操作时几乎完全一样的.
(4)简化代码
采用innerHTML
增删DOM练习
姓名
年龄
薪水
操作
Tom
12
3000
删除
Jim
18
4000
删除
姓名:
年龄:
薪资:
最终的效果: