一. JS 的面向对象
JS没有类,其类就用function来代替如下所示:
1 function Cat(name, color){
2 this.name=name;
3 this.color=color;
4 }
这就相当于是构造函数,可以生成对象:
1 // 声明Cat对象
2 var cat1 = new Cat("jack", "yellow");
3 var cat2 = new Cat("tom","black");
4
5 // 用法和其他语言的对象一样
6 alert(cat1.name); // jack
7 alert(cat1.color); // yellow
但是js的构造函数里面所有的东西都是储存在对象上面的,所以如果在里面定义func就很浪费内存,因为func都是一样的,别的语言都是放到类的内存里的,如下这样的 eat 的方法就是浪费:
1 function Cat(name,color){
2 this.name = name;
3 this.color = color;
4 this.type = "catamount";
5 this.eat = function(){
6 alert("Eat mouse");
7 };
8 }
所以js的每个构造函数都有一个prototype属性,这个对象的所有属性和方法,都会被构造函数的实例继承,存储到了类里。这样就做到了类似类属性,和方法的效果;示例如下:
1 function Cat(name,color){
2 this.name = name;
3 this.color = color;
4 }
5 Cat.prototype.type = "catamount";
6 Cat.prototype.eat = function(){
7 alert("Eat mouse")
8 };
二. 用JS移动和复制元素
我们知道用JS可以通过appendChild之类的方法动态地在元素里添加新元素,但是如果这个新元素,本身就是通过DOM获取到的其他元素,那么这个过程就是一个移动的过程,也就是说会从原本的位置去除,放到这个新的位置,示例如下:
1 <h2 id="h1">1111</h2>
2 <div id="container">
3 <div>1</div>
4 <div>2</div>
5 </div>
原HTML页面显示结果:
加入如下JS:
1 <script>
2 var h1 = document.getElementById('h1');
3 var ct = document.getElementById('container');
4 ct.appendChild(h1);
5 </script>
显示结果:
所以如果是想要选择一个元素,并将之复制到另外一个位置的话需要使用coleNode方法:
1 <script>
2 var h1 = document.getElementById('h1');
3 var ct = document.getElementById('container');
4 //ct.appendChild(h1);
5 var h2 = h1.cloneNode(true);
6 ct.appendChild(h2);
7 </script>
注意如果是普通的声明一个新变量并赋值,那并不会生成一个新的元素;此外cloneNode中的true效果是会clone整个tag内部所有的内容,不加的话只会clonetag。
三. JQUERY给动态生成的元素绑定事件
我们常常会面对需要动态给页面增添HTML元素的场景,而如果我们想要对这些元素进行操作的话,和普通的元素上会有区别。因为js代码是自上而下读取代码进行解释的,所以一段操作元素的代码(比如使用选择器选中元素并修改其属性)在某个元素生成的代码执行前,那么这段操作是无法起效的。
比如我有下述一个table元素,其中只包含了一个tr元素:
1 <table width="600" id="row_table">
2 <tr class="row">
3 <td><input type="text"/></td>
4 <td><input type="text"/></td>
5 <td>
6 <select class="sel">
7 <option value ="s1">s1</option>
8 <option value ="s2">s2</option>
9 </select>
10 </td>
11 </tr>
12 </table>
然后我会通过代码动态,给一个按钮加入新增tr元素的功能:
1 single_row = '<tr class="row"><td><input type="text"/></td><td><input type="text"/></td><td><select class="sel"><option value ="s1">s1</option><option value ="s2">s2</option></select></td></tr>'
2 $("#add").click(function(){
3 $("#row_table").append(single_row);
4 })
如果想要为select元素添加一个change事件:
1 $(".sel").change(function(){
2 multi_select($(this));
3 })
会发现只有原本那个在HTML里面就有的元素才被操作了,所有后续新加的tr元素内的select都没有被操作到。
为解决这种问题有几种方法,第一种方法是使用JQUERY的on方法(jquery1.9版本以上,老的版本可以用live啥的方法貌似),选择器选中会动态动态添加子元素的父元素,然后再通过选择其内部的子元素,加上事件及对应操作函数,示例如下:
1 $("table").on("change", ".sel", function(){
2 multi_select($(this));
3 })
第二种方法思路更加简单,就是在动态添加元素的时候,在元素的HTML标签中直接加入事件的tag和方法就好了:
1 <select class="sel" onchange="multi_select();">
第三种方法其实和上面类似,就是用js生成元素而不是直接添加HTML,然后在生成元素的时候,直接用JS使用bind方法绑定事件就好了。就不演示了。
四. 事件绑定函数的入参
使用click, change等等方法给元素绑定事件,其中一个入参为事件触发后的处理函数,这个函数其实是有一个入参的:
1 $("#reverse").click(function(event){
2 console.log(event);
3 }
我们打印看一下,会发现这是一个Event,会记录一些事件相关的信息,比如是鼠标事件啦,是点击啦啥的,和绑定的事件、元素相关:
再比如这个keydown事件,我们看一下event:
1 $(window).keydown(function(event){
2 console.log(event);
3 })
有一个重要的属性keyCode,这就是按下的键盘按键的一个编号;我给window添加了监控键盘按下的事件,并获取keyCode就能随时知道键盘是不是按了某个键,然后就可以进一步做些组合操作啥的。
五. $.each和$.map的用法与区别
在使用Jquery的过程中,我注意到了$.each和$.map两个函数,一开始有些迷惑它们之间的区别,因为看起来好像都是遍历对象/数组做操作。这里记录一下自己学习的使用方法,已经区别。
先来看一些each的使用实例:
1. 使用each遍历一个对象,然后打印其入参:
1 li={a:1,b:2}
2 $.each(li, function(x,y){
3 console.log(x,y)
4 })
我们可以知道第一个入参是对象的属性名,第二个入参是属性值。
2. 使用each遍历一个数组,打印其入参:
1 list = [11,22,33,44];
2 $.each(list, function(i, v){
3 console.log(i, v)
4 })
课件第一个入参是索引,第二个入参是值。
3. 再让我们在each的方法里面加入return看看:
结果返回的是each的第一个参数;同时综合以上几个例子,我们可以发现,each方法会自动返回一个对象(无论你加不加return,无论return什么东西),这个对象都是我们交给each去处理的第一个参数,一个对象或序列。也就是说each调用的方法,其return的内容被忽略了,外部是获取不到的。
4. 还有一个特殊的用法,即在调用的方法中return false。
结果就是return false会中断each的遍历!
我这里摘录了对each的官方描述,对以上的行为都做了说明,看起来非常精彩:
然后再来看map的一些使用实例:
1. map遍历一个对象,输出入参:
可见map入参获取到的顺序和each是相反的,其第一个入参是值,第二个才是属性名称。返回值是一个空数组,而each是原对象。
2. 遍历一个序列:
map入参获取到的顺序也和each是相反的,其第一个入参是值,第二个才是索引。此外返回值是一个空数组,而each是原数组。
3. 遍历对象,分别reutrn第一个和第二个入参:
这回我们的返回值不再是空数组了,当然还是一个数组。其内容就是我们每次遍历调用函数内部return出来的值。
综合上面几个例子,我们可以知道map返回值都是数组,其每个元素就是每次遍历调用函数内部return出来的值,这个行为和python中的内建函数map非常相似。
不过map也有些需要注意的地方(对我来说主要是和python的map表现不同的需要理解和记住的地方...)!!!!
1. 在map调用的函数中返回null,并不是在结果数组中加入一个null,而是相当于不返回,或者认为去掉了一个元素,示例如下:
2. 在map调用的函数中返回数组,其最终的结果数组并不是每个元素都是函数中返回的数组(也就是不是数组套数组),而是将每次返回的数组里的每个元素都依次加入到最终结果的数组中,也就是说结果数组看起来被扩张了(类似python的extend的感觉,而不是append),示例如下:
这里可以看到原数组里的值和索引都被加入到最终的结果数组里了。
最后同样摘录官网的描述!