HTML&CSS学习总结+js学习总结(3)

-----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操作


1遍历对象的属性

for-in语句可以用于遍历对象的属性名及属性值。

for(var attribute_name in obj){
    console.log(obj[attribute_name]);
    }

访问对象有两种方式“.”和[],因为这里用到了变量,所以只能使用obj[attribute_name]的方法实现

2js中的作用域

2.1变量作用域

  • 全局作用域。全局作用域在页面打开时创建,页面关闭时销毁,全局作用域中创建的变量都会作为window的对象属性保存。因此直接 为一个变量赋值而不声明,会认为是为window添加的属性。

注:声明但不赋值与未声明的变量都是undefined的,而使用访问未声明的变量会报错,但是访问声明的变量只会按undefined类型处理。

  • 声明提前
var a =5;

使用var关键字声明的变量,会在所有代码执行之前被声明,赋值是在改代码原来所在位置执行。

除此之外,函数创建中的声明形式也会被声明提前,也即如下代码是可以执行的,因为fun的函数被声明提前。

fun();


function fun(){
//函数体
}

2.2函数作用域

  • 每调用一次,函数就会创建一个新的函数作用域,他们之间的访问时互相独立的。
  • 函数作用域可以访问到全局作用域的变量(全局变量),全局作用域无法访问到函数作用域的变量。
  • 当在函数作用域中操作一个变量,它会先在自身变量作用域寻找,如果有就使用,如果没有向上一级寻找,上一级没有再向上一级访问,以此类推,直至在全局作用域没有访问到,就报错。
  • 如果想跳过上述的变量搜寻准则,可以直接使用window.变量名访问全局作用域中的方法和变量
  • 在函数作用域也有变量提前,是在函数代码执行之初就已经变量声明。
  • 在函数内部,不使用var声明直接赋值的变量,会被当成是window的属性添加进去。
  • 形参,相当于在函数作用域中声明。

2.3函数闭包

 

3DEBUG

  • 选中要观察的变量,右键   添加监控(add selected text to watches)
  • 但步执行快捷键:F10

4this的情况

解析器就是浏览器,解析器在调用函数每次都会向函数内部穿传递一个隐含参数,这个隐含的参数是this。this指向一个对象,这对象我们称之为上下文对象,根据函数的调用方式不同,this指向不同的对象

(1)以函数的形式调用。this指的永远是window,不管是在函数内部再创建函数,还是将函数返回。

function fun(){
alert(this);
  function fun1(){
  alert(this);
  }
 return fun1;
}
fun()();

运行结果

HTML&CSS学习总结+js学习总结(3)_第1张图片HTML&CSS学习总结+js学习总结(3)_第2张图片

(2)以方法的形式调用。this指的是调用方法的对象。

(3)以构造函数的形式调用。this指的是新创建的那个对象

(4)使用call和apply调用时,this为指定的那个对象。

(5)事件的响应函数中,响应函数给谁绑定,this就指的谁。

5对象的创建

5.1工厂模式

封装为一个函数,传进来对象的属性值,方法体。

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类型的。

5.2构造函数模式

构造函数与普通的函数类似,为了区别于普通函数,将构造函数的首字母大写。

构造函数的创建流程

  1. 立即创建一个新对象
  2. 将新建对象设置为函数中的this
  3. 执行构造函数中的代码
  4. 将新建对象作为返回值返回

类的概念

由于引入了构造函数,我们称使用同一个构造函数创建的对象,我们称之为一类对象,也将一个构造函数成为一个类。可以通过 instanceof 判断一个对象是否是一个类的实例。

语法:如果对象是构造函数的一个实例,返回true,否则返回false

对象名  instanceof 构造函数

缺陷:每个新的对象都会在堆区开辟一片内存空间放置变量的属性和方法,每个对象的地址是不同的,所以不同的对象也是独立。事实上有一些属性和方法是可以共用的,这些重复的属性和方法浪费了内存空间。

一种解决办法是在全局作用域创建相关的属性和函数,然后为对象赋相同的函数对象地址,从而保证所有一个类下的对象共用一个方法。但是这种方法会污染全局作用域的命名空间,而且很不安全。

5.3原型创建对象

每创建一个函数,解析器会向函数对象添加一个属性 prototype(原型),这个属性对应于一个对象,称为原型对象。

用图:原型对象保存着  所有通过同一构造函数创建的实例的共有属性和方法。通过原型对象可以实现方法和属性的共用。

创建方法:

  1. 使用构造函数。Person.prototype.sayName = function(){}
  2. 使用已经实例化的对象。per1.__proto__.sayName = function(){}

使用方法:

  • 当我们访问一个对象的属性或者方法时,会先在对象自身中寻找,如果有就使用,没有再去原型中寻找。
  • 使用in可以检查对象中是否含有某个属性,但是如果对象自身中没有,而在原型对象中含有使用in也会返回true。如果想检测自身是够含有该属性,可使用对象的hasOwnProperty()方法检查自身是够含有该属性。
  • 原型对象也是对象,也含有隐含的属性:原型对象
  • 例如想修改对象原有的toString()方法,可以类额原型中编写自定义的toString方法。

6数组(Array)

  • 创建数组

字面量创建: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的项组成的数组。

  • 数组中的slice和splic方法

(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有很多功能:

  1. 删除元素。参数3及以后参数缺省

  2. 替换元素。参数2不为空,有参数3以后的参数

  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的书,顺序都不变。

7函数

  • call和apply方法。这两个都是函数对象的方法,需要通过函数对象调用。

功能:当对函数调用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属性

调用函数时,浏览器都会穿给函数两个隐含参数:

  1. this的上下文对象
  2. 包含实参的对象arguments

注意:arguments可以用数组索引的方式访问,但是只是类数组对象,不是数组,arguments instanceOf Array返回false,Array.isArray(arguments)也返回的是false。arguments中有一个属性callee,表示当前正在执行的函数对象

8Date对象

  • 创建Date对象

var d = new Date();

直接用构造函数(缺省参数)创建的Date对象,指的当前代码执行的时间。如果在构造函数中传入“月份/日/年  时:分:秒”的字符串,d指的就是这个时间。

  • 使用Date对象

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();  获取当前代码执行时的时间戳

9window和Global对象

web浏览器将Global对象作为window的一部分加以实现,isNaN、isFinite、parseInt以及parseFloat实际上都是global对象的方法。

10包装类

  • String、Number、Boolean

功能:将基本的数据类型转化为对象,这样可以使用对象的方式(方法和属性)对基本数据类型进行处理。因为方法和属性只能添加给对象,不能添加给基本数据类型。

但是,开发中一般不用包装类,因为会产生一些不可预料的后果。

引入包装类的原因:当我们对一些基本数据类型去访问属性、方法时,浏览器会临时使用包装类将基本数据类型转化为对象,然后调用对象的属性和方法,调用完再转化为基本数据类型。这也就是所谓的装箱拆箱。包装类可以帮助我们理解这一特性。

所以,我们可以通过基本数据的包装类的原型去设置一些方法和属性,方便装箱拆箱的时候使用。

  • String是最常用的包装类

字符串在底层是以字符数组的形式保存的。以下方法不会对源字符串产生影响,产生变化的字符串都会作为返回值返回,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只能传入字符串。

11DOM操作

DOM是API,是JavaScript为了操作HTML文档所提供的接口。document指的就是整个文档。

(1)节点

每个节点都是一个对象,共有四种节点:文档节点、元素节点、属性节点、文本节点。

(2)获取节点对象的方法

  1. 通过document。有:getElementById,通过标签的ID属性获得元素节点对象;getElementsByTagName通过标签名获取一组节点对象,封装到一个数组当中,即使只有一个节点对象,也是用长度为1的数组包装;getElementsByName,数组的特性特性与getElementsByTagName类似,但是这种方式主要用于操作表单项。
  2. 获取节点的子节点对象。有:getElementsByTagName,返回当前节点的指定标签名后代的元素节点;childNodes属性,表示当前节点的所有子节点;firstChild属性,子节点中第一个子节点;lastChild属性,最后一个子节点。
  3. children属性,获取当前元素的所有子元素。
  4. parentNode。获取元素父元素
  5. previousSibling。返回当前元素的前一个兄弟节点
  6. nextSibling。获取当前节点的后一个兄弟节点
  7. 获取body节点对象。var body = document.getElementsByTagName("body")[0]; 另外,document中有一个属性body保存的是body的引用。
  8. html = document.documentElement;
  9. all = document.all;
  10. 根据CSS选择器查询一个元素节点对象。document.querySelector(".box1 div");IE8中虽然没有getElementsByClassName,但是可以使用querySelector代替,但是它只能返回唯一的元素对象(第一个满足条件的元素对象),即使满足条件的元素节点对象有多个。
  11. querySelectorAll。该方法与querySelector类似,不同的是它将符合条件的元素封装到一个数组中,解释只有一个元素对象符合条件,也会封装到长度为1的数组中。

注:上边标红的节点,可能包含文本节点对象,所以如果仅仅选中元素节点的话,应避免使用。

(3)DOM增删改

  • 创建元素节点对象——createElement()

语法:document.createElement("....");

用法:它需要一个标签名作为参数,并根据标签名创建元素节点对象,并将创建好的节点对象返回。

  • 创建文本节点对象——createTextNode()

语法:document.createTextNode(".....");

用法:需要文本内容作为参数,并根据该内容创建文本节点,并将节点返回。

  • 添加新节点——appendChild();

语法: 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);

    练习

    表格+表单实现 对表格的增删操作

    HTML&CSS学习总结+js学习总结(3)_第3张图片

    思路:

    (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

    HTML&CSS学习总结+js学习总结(3)_第4张图片

    
    
    
    	
    	增删DOM练习
    	
    	
    
    
    	
    姓名 年龄 薪水 操作
    Tom 12 3000 删除
    Jim 18 4000 删除
    姓名:
    年龄:
    薪资:

    最终的效果:

    HTML&CSS学习总结+js学习总结(3)_第5张图片

     

    你可能感兴趣的:(html&css学习)