JavaScript操作

JavaScript

字符串

JavaScript的字符串就是用 ''""括起来的字符表示。

如果'本身也是一个字符,那就可以用""括起来,比如 "I'm OK" 包含的字符是 I , ’ , m ,空格, O , K 这6个字符。

如果字符串内部既包含'又包含"怎么办?可以用转义字符\来标识,比如:

'I\'m \"OK\"!';

常用方法

JavaScript为字符串提供了一些常用方法,注意,调用这些方法本身不会改变原有字符串的内容,而是返 回一个新字符串

  • toUpperCase() 把一个字符串全部变为大写

    var s = 'Hello';
    s.toUpperCase(); // 返回'HELLO'
    
  • toLowerCase() 把一个字符串全部变为小写

    var s = 'Hello';
    var lower = s.toLowerCase(); // 返回'hello'并赋值给变量lower
    lower; // 'hello'
    
  • indexOf() 会搜索指定字符串出现的位置

    var s = 'hello, world';
    s.indexOf('world'); // 返回7
    s.indexOf('World'); // 没有找到指定的子串,返回-1
    
  • substring() 返回指定索引区间的子串

    var s = 'hello, world'
    s.substring(0, 5); // 从索引0开始到5(不包括5),返回'hello'
    s.substring(7); // 从索引7开始到结束,返回'world'
    

数组

JavaScript的 Array可以包含任意数据类型,并通过索引来访问每个元素。

请注意,直接给 Arraylength 赋一个新的值会导致Array大小的变化

var arr = [1, 2, 3];
arr.length; // 3
arr.length = 6;
arr; // arr变为[1, 2, 3, undefined, undefined, undefined]
arr.length = 2;
arr; // arr变为[1, 2]

如果通过索引赋值时,索引超过了范围,同样会引起 Array 大小的变化:

var arr = [1, 2, 3];
arr[5] = 'x';
arr; // arr变为[1, 2, 3, undefined, undefined, 'x']

常用方法

  • indexOf:与String类似, Array 也可以通过 indexOf() 来搜索一个指定的元素的位置:

    var arr = [10, 20, '30', 'xyz'];
    arr.indexOf(10); // 元素10的索引为0
    arr.indexOf(20); // 元素20的索引为1
    arr.indexOf(30); // 元素30没有找到,返回-1
    arr.indexOf('30'); // 元素'30'的索引为2
    

    注意了,数字 30 和字符串 ‘30’ 是不同的元素。

  • slice:slice() 就是对应String的 substring() 版本,它截取 Array 的部分元素,然后返回一个 新的 Array.

    var arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
    arr.slice(0, 3); // 从索引0开始,到索引3结束,但不包括索引3: ['A', 'B', 'C']
    arr.slice(3); // 从索引3开始到结束: ['D', 'E', 'F', 'G']
    

    如果不给 slice() 传递任何参数,它就会从头到尾截取所有元素。利用这一点,我们可以很容 易地复制一个 Array :

    var arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
    var aCopy = arr.slice();
    aCopy; // ['A', 'B', 'C', 'D', 'E', 'F', 'G']
    aCopy === arr; // false
    
  • push和pop:push() 向 Array 的末尾添加若干元素, pop() 则把 Array 的最后一个元素删除掉

    var arr = [1, 2];
    arr.push('A', 'B'); // 返回Array新的长度: 4
    arr; // [1, 2, 'A', 'B']
    arr.pop(); // pop()返回'B'
    arr; // [1, 2, 'A']
    arr.pop(); arr.pop(); arr.pop(); // 连续pop 3次
    arr; // []
    arr.pop(); // 空数组继续pop不会报错,而是返回undefined
    arr; // []
    
  • unshift和shift:如果要往 Array 的头部添加若干元素,使用 unshift() 方法, shift() 方法则把 Array 的第一个元素删掉:\

    var arr = [1, 2];
    arr.unshift('A', 'B'); // 返回Array新的长度: 4
    arr; // ['A', 'B', 1, 2]
    arr.shift(); // 'A'
    arr; // ['B', 1, 2]
    arr.shift(); arr.shift(); arr.shift(); // 连续shift 3次
    arr; // []
    arr.shift(); // 空数组继续shift不会报错,而是返回undefined
    arr; // []
    
  • sort:sort() 可以对当前 Array 进行排序,它会直接修改当前 Array 的元素位置,直接调用 时,按照默认顺序排序

    var arr = ['B', 'C', 'A'];
    arr.sort();
    arr; // ['A', 'B', 'C']
    
  • reverse:reverse() 把整个 Array 的元素给掉个个,也就是反转

    var arr = ['one', 'two', 'three'];
    arr.reverse();
    arr; // ['three', 'two', 'one']
    
  • splice:splice() 方法是修改 Array 的“万能方法”,它可以从指定的索引开始删除若干元素,然后再 从该位置添加若干元素

    var arr = ['Microsoft', 'Apple', 'Yahoo', 'AOL', 'Excite', 'Oracle'];
    // 从索引2开始删除3个元素,然后再添加两个元素:
    arr.splice(2, 3, 'Google', 'Facebook'); // 返回删除的元素 ['Yahoo', 'AOL',
    'Excite']
    arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
    // 只删除,不添加:
    arr.splice(2, 2); // ['Google', 'Facebook']
    arr; // ['Microsoft', 'Apple', 'Oracle']
    // 只添加,不删除:
    arr.splice(2, 0, 'Google', 'Facebook'); // 返回[],因为没有删除任何元素
    arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
    
  • concat:concat() 方法把当前的 Array 和另一个 Array 连接起来,并返回一个新的 Array

    var arr = ['A', 'B', 'C'];
    var added = arr.concat([1, 2, 3]);
    added; // ['A', 'B', 'C', 1, 2, 3]
    arr; // ['A', 'B', 'C']
    

    concat() 方法并没有修改当前 Array ,而是返回了一个新的 Array 。 实际上, concat() 方法可以接收任意个元素和 Array ,并且自动把 Array 拆开,然后全 部添加到新的 Array 里:

    var arr = ['A', 'B', 'C'];
    arr.concat(1, 2, [3, 4]); // ['A', 'B', 'C', 1, 2, 3, 4]
    
  • join:join() 方法是一个非常实用的方法,它把当前 Array 的每个元素都用指定的字符串连接起 来,然后返回连接后的字符串:

    var arr = ['A', 'B', 'C', 1, 2, 3];
    arr.join('-'); // 'A-B-C-1-2-3'
    
  • 多维数组:如果数组的某个元素又是一个 Array ,则可以形成多维数组,例如:

    var arr = [[1, 2, 3], [400, 500, 600], '-'];
    

    上述 Array 包含3个元素,其中头两个元素本身也是 Array 。

    练习:如何通过索引取到 500 这个值:

    var x = arr[1][2];
    console.log(x); // x应该为500
    

对象

JavaScript的对象是一种无序的集合数据类型,它由若干键值对组成。

由于JavaScript的对象是动态类型,你可以自由地给一个对象添加或删除属性:

var xiaoming = {
	name: '小明'
};
xiaoming.age; // undefined
xiaoming.age = 18; // 新增一个age属性
xiaoming.age; // 18
delete xiaoming.age; // 删除age属性
xiaoming.age; // undefined
delete xiaoming['name']; // 删除name属性
xiaoming.name; // undefined
delete xiaoming.school; // 删除一个不存在的school属性也不会报错

如果我们要检测对象是否拥有某一属性,可以用 in 操作符:

'name' in xiaoming; // true
'grade' in xiaoming; // false

要判断一个属性是否是 xiaoming 自身拥有的,而不是继承得到的,可以用 hasOwnProperty() 方法:

xiaoming.hasOwnProperty('name'); // true
xiaoming.hasOwnProperty('toString'); // false

流程控制

if判断

var age = 3;
if (age >= 18) {
	alert('adult');
} else if (age >= 6) {
	alert('teenager');
} else {
	alert('kid');
}

for循环

基础语法

var x = 0;
var i;
for (i=1; i<=10000; i++) {
	x = x + i;
}
x; // 50005000

遍历数组

var arr = ['Apple', 'Google', 'Microsoft'];
var i, x;
for (i=0; i<arr.length; i++) {
    x = arr[i];
    console.log(x);
}

无限循环

var x = 0;
for (;;) { // 将无限循环下去
    if (x > 100) {
    	break; // 通过if判断来退出循环
    }
    x ++;
}

for … in , 它可以把一个对象的所有属性依次循环出来:

var o = {
    name: 'Jack',
    age: 20,
    city: 'Beijing'
};
for (var key in o) {
    if (o.hasOwnProperty(key)) {
   		 console.log(key); // 'name', 'age', 'city'
    }
}

由于 Array 也是对象,而它的每个元素的索引被视为对象的属性,所以遍历出来是下标

var a = ['A', 'B', 'C'];
for (var i in a) {
    console.log(i); // '0', '1', '2'
    console.log(a[i]); // 'A', 'B', 'C'
}

请注意,for ... inArray 的循环得到的是String而不是Number

while循环

基本操作

var x = 0;
var n = 99;
while (n > 0) {
    x = x + n;
    n = n - 2;
}
x; // 2500

do…while

var n = 0;
do {
	n = n + 1;
} while (n < 100);
n; // 100

在编写循环代码时,务必小心编写初始条件和判断条件,尤其是边界值。 特别注意 i < 100 和 i <= 100 是不同的判断逻辑。

Map 和 Set

ES6规范引入了新的数据类型 Map 和Set。

Map

Map 是一组键值对的结构,具有极快的查找速度。

var m = new Map(); // 空Map
m.set('Adam', 67); // 添加新的key-value
m.set('Bob', 59);
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined

Set

Set 和 Map 类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在 Set 中, 没有重复的key。

var s = new Set([1, 2, 3]);
s; // Set {1, 2, 3}
s.delete(3);
s; // Set {1, 2}
s.add(4);

Iterable

遍历 Array 可以采用下标循环,遍历Map 和 Set 就无法使用下标。 为了统一集合类型,ES6标准引入了新的 iterable 类型,Array,Map,Set 属于; 具有 iterable 类型的集合可以通过新的 for … of 循环来遍历。

var a = ['A', 'B', 'C'];
var s = new Set(['A', 'B', 'C']);
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
for (var x of a) { // 遍历Array
	console.log(x);
}
for (var x of s) { // 遍历Set
	console.log(x);
}
for (var x of m) { // 遍历Map
	console.log(x[0] + '=' + x[1]);
}

更好的方式是直接使用 iterable 内置的 forEach 方法,它接收一个函数,每次迭代就自动回调该 函数。以 Array 为例

a.forEach(function (element, index, array) {
    // element: 指向当前元素的值
    // index: 指向当前索引
    // array: 指向Array对象本身
    console.log(element + ', index = ' + index);
});

Set 没有索引,因此回调函数的前两个参数都是元素本身:

var s = new Set(['A', 'B', 'C']);
s.forEach(function (element, sameElement, set) {
	console.log(element);
});	

Map 的回调函数参数依次为 value 、 key 和 map 本身:

var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
m.forEach(function (value, key, map) {
	console.log(value);
});

函数

函数定义和调用

//方式一
function abs(x) {
    if (x >= 0) {
        return x;
    } else {
        return -x;
    }
}

//方式二
var abs = function (x) {
    if (x >= 0) {
    	return x;
    } else {
   	 return -x;
    }
};


//调用
abs(10); // 返回10
abs(-9); // 返回9

方法

function getAge() {
var y = new Date().getFullYear();
return y - this.birth;
}
var xiaoming = {
name: '小明',
birth: 1990,
age: getAge
};
xiaoming.age(); // 25, 正常结果
getAge(); // NaN

Date

在JavaScript中, Date 对象用来表示日期和时间。注意,当前时间是浏览器从本机操作系统获取的时间

var now = new Date();
now; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
now.getFullYear(); // 2015, 年份
now.getMonth(); // 5, 月份,注意月份范围是0~11,5表示六月
now.getDate(); // 24, 表示24号
now.getDay(); // 3, 表示星期三
now.getHours(); // 19, 24小时制
now.getMinutes(); // 49, 分钟
now.getSeconds(); // 22, 秒
now.getMilliseconds(); // 875, 毫秒数
now.getTime(); // 1435146562875, 以number形式表示的时间戳
var d = new Date(1435146562875);
d.toLocaleString(); // '2015/6/24 下午7:49:22',本地时间(北京时区+8:00),显示的字
符串与操作系统设定的格式有关
d.toUTCString(); // 'Wed, 24 Jun 2015 11:49:22 GMT',UTC时间,与本地时间相差8小时

JSON

JSON 和 JavaScript 对象互转

  • 要实现从JSON字符串转换为JavaScript 对象,使用 JSON.parse() 方法:

    var obj = JSON.parse('{"a": "Hello", "b": "World"}');
    //结果是 {a: 'Hello', b: 'World'}
    
  • 要实现从JavaScript 对象转换为JSON字符串,使用 JSON.stringify() 方法:

    var json = JSON.stringify({a: 'Hello', b: 'World'});
    //结果是 '{"a": "Hello", "b": "World"}'
    

操作BOM

window

window对象不但充当全局作用域,而且表示浏览器窗口。 window 对象有 innerWidthinnerHeight属性,可以获取浏览器窗口的内部宽度和高度。 内部宽高是指除去菜单栏、工具栏、边框等占位元素后,用于显示网页的净宽高。

兼容性:IE<=8不支持。

'use strict';
// 可以调整浏览器窗口大小试试:
console.log('window inner size: ' + window.innerWidth + ' x ' +
window.innerHeight);

对应的,还有一个outerWidthouterHeight属性,可以获取浏览器窗口的整个宽高。

navigator

navigator对象表示浏览器的信息,最常用的属性包括:

  • navigator.appName:浏览器名称;
  • navigator.appVersion:浏览器版本;
  • navigator.language:浏览器设置的语言;
  • navigator.platform:操作系统类型;
  • navigator.userAgent:浏览器设定的 User-Agent 字符串。
'use strict';
console.log('appName = ' + navigator.appName);
console.log('appVersion = ' + navigator.appVersion);
console.log('language = ' + navigator.language);
console.log('platform = ' + navigator.platform);
console.log('userAgent = ' + navigator.userAgent);

screen

screen对象表示屏幕的信息,常用的属性有:

  • screen.width:屏幕宽度,以像素为单位;
  • screen.height:屏幕高度,以像素为单位;
  • screen.colorDepth:返回颜色位数,如8、16、24。

location

location对象表示当前页面的URL信息。例如,一个完整的URL:

 http://www.example.com:8080/path/index.html?a=1&b=2#TOP

可以用 location.href 获取。要获得URL各个部分的值,可以这么写:

location.protocol; // 'http'
location.host; // 'www.example.com'
location.port; // '8080'
location.pathname; // '/path/index.html'
location.search; // '?a=1&b=2'
location.hash; // 'TOP'

要加载一个新页面,可以调用location.assign()。如果要重新加载当前页面,调用 location.reload()方法非常方便。

location.reload();
location.assign('https://blog.kuangstudy.com/'); // 设置一个新的URL地址

document

document对象表示当前页面。由于HTML在浏览器中以DOM形式表示为树形结构, document对 象就是整个DOM树的根节点。

documenttitle属性是从HTML文档中的 xxx 读取的,但是可以动态改变:请观察浏览器窗口标题的变化。

document.title = 'javascript';

要查找DOM树的某个节点,需要从 document对象开始查找。最常用的查找是根据ID和Tag Name。 我们先准备HTML数据:

<dl id="code-menu" style="border:solid 1px #ccc;padding:6px;">
    <dt>Java</dt>
    <dd>Spring</dd>
    <dt>Python</dt>
    <dd>Django</dd>
    <dt>Linux</dt>
    <dd>Docker</dd>
</dl>

用 document 对象提供的 getElementById()getElementsByTagName()可以按ID获得一个 DOM节点和按Tag名称获得一组DOM节点:

var menu = document.getElementById('code-menu');
var drinks = document.getElementsByTagName('dt');
var i, s;
s = '提供的饮料有:';
for (i=0; i<drinks.length; i++) {
	s = s + drinks[i].innerHTML + ',';
}
console.log(s);

document对象还有一个 cookie 属性,可以获取当前页面的Cookie。

document.cookie; // 'v=123; remember=true; prefer=zh'

操作DOM

选择器

由于HTML文档被浏览器解析后就是一棵DOM树,要改变HTML的结构,就需要通过JavaScript来操作 DOM。

始终记住DOM是一个树形结构。操作一个DOM节点实际上就是这么几个操作:

  • 更新:更新该DOM节点的内容,相当于更新了该DOM节点表示的HTML的内容;
  • 遍历:遍历该DOM节点下的子节点,以便进行进一步操作;
  • 添加:在该DOM节点下新增一个子节点,相当于动态增加了一个HTML节点;
  • 删除:将该节点从HTML中删除,相当于删掉了该DOM节点的内容以及它包含的所有子节点。

在操作一个DOM节点前,我们需要通过各种方式先拿到这个DOM节点。最常用的方法是document.getElementById()document.getElementsByTagName() ,以及CSS选择器 document.getElementsByClassName()

由于ID在HTML文档中是唯一的,所以 document.getElementById()可以直接定位唯一的一个DOM 节点。 document.getElementsByTagName()document.getElementsByClassName()总是返 回一组DOM节点(数组)。要精确地选择DOM,可以先定位父节点,再从父节点开始选择,以缩小范围。(数组选择)

// 返回ID为'test'的节点:
var test = document.getElementById('test');
// 先定位ID为'test-table'的节点,再返回其内部所有tr节点:
var trs = document.getElementById('test-table').getElementsByTagName('tr');
// 先定位ID为'test-div'的节点,再返回其内部所有class包含red的节点:
var reds = document.getElementById('testdiv').getElementsByClassName('red');
// 获取节点test下的所有直属子节点:
var cs = test.children;
// 获取节点test下第一个、最后一个子节点:
var first = test.firstElementChild;
var last = test.lastElementChild;

第二种方法是使用 querySelector()querySelectorAll(),需要了解selector语法,然后使 用条件来获取节点,更加方便:

// 通过querySelector获取ID为q1的节点:
var q1 = document.querySelector('#q1');
// 通过querySelectorAll获取q1节点内的符合条件的所有节点:
var ps = q1.querySelectorAll('div.highlighted > p');

注意:低版本的IE<8不支持 querySelector 和 querySelectorAll 。IE8仅有限支持。

更新DOM

拿到一个DOM节点后,我们可以对它进行更新。

可以直接修改节点的文本,方法有两种:

一种是修改 innerHTML属性,这个方式非常强大,不但可以修改一个DOM节点的文本内容,还可以 直接通过HTML片段修改DOM节点内部的子树:

// 获取<p id="p-id">...</p>
var p = document.getElementById('p-id');
// 设置文本为abc:
p.innerHTML = 'ABC'; // <p id="p-id">ABC</p>
// 设置HTML:
p.innerHTML = 'ABC <span style="color:red">RED</span> XYZ';
// <p>...</p>的内部结构已修改

innerHTML时要注意,是否需要写入HTML。如果写入的字符串是通过网络拿到了,要注意对字符 编码来避免XSS攻击。

第二种是修改innerText属性,这样可以自动对字符串进行HTML编码,保证无法设置任何HTML标 签:

// 获取<p id="p-id">...</p>
var p = document.getElementById('p-id');
// 设置文本:
p.innerText = '<script>alert("Hi")</script>';
// HTML被自动编码,无法设置一个<script>节点:
// <p id="p-id">&lt;script&gt;alert("Hi")&lt;/script&gt;</p>

修改CSS也是经常需要的操作。DOM节点的style属性对应所有的CSS,可以直接获取或设置。因为 CSS允许 font-size这样的名称,但它并非JavaScript有效的属性名,所以需要在JavaScript中改写为 驼峰式命名fontSize

// 获取<p id="p-id">...</p>
var p = document.getElementById('p-id');
// 设置CSS:
p.style.color = '#ff0000';
p.style.fontSize = '20px';
p.style.paddingTop = '2em';

插入DOM

appendChild

<!-- HTML结构 -->
<p id="js">JavaScript</p>
<div id="list">
    <p id="java">Java</p>
    <p id="python">Python</p>
    <p id="scheme">Scheme</p>
</div>

很多的时候我们会从零创建一个新的节点,然后插入到指定位置:

var
    list = document.getElementById('list'),
    haskell = document.createElement('p');
haskell.id = 'haskell';
haskell.innerText = 'Haskell';
list.appendChild(haskell);

这样我们就动态添加了一个新的节点:

<!-- HTML结构 -->
<div id="list">
    <p id="java">Java</p>
    <p id="python">Python</p>
    <p id="scheme">Scheme</p>
    <p id="haskell">Haskell</p>
</div>

举个例子,下面的代码动态创建了一个 节点,然后把它添加到 节点的末尾,这样就动态地给文档添加了新的CSS定义:

var d = document.createElement('style');
d.setAttribute('type', 'text/css');
d.innerHTML = 'p { color: red }';
//head 头部标签
document.getElementsByTagName('head')[0].appendChild(d);

insertBefore

如果我们要把子节点插入到指定的位置怎么办?可以使用 parentElement.insertBefore(newElement, referenceElement);,子节点会插入到 referenceElement之前。

还是以上面的HTML为例,假定我们要把 Haskell 插入到 Python 之前:

<!-- HTML结构 -->
<div id="list">
    <p id="java">Java</p>
    <p id="python">Python</p>
    <p id="scheme">Scheme</p>
</div>

可以这么写:

var
    list = document.getElementById('list'),
    ref = document.getElementById('python'),
haskell = document.createElement('p');
haskell.id = 'haskell';
haskell.innerText = 'Haskell';
list.insertBefore(haskell, ref);

新的HTML结构如下:

<!-- HTML结构 -->
<div id="list">
    <p id="java">Java</p>
    <p id="haskell">Haskell</p>
    <p id="python">Python</p>
    <p id="scheme">Scheme</p>
</div>

删除DOM

删除一个DOM节点就比插入要容易得多。 要删除一个节点,首先要获得该节点本身以及它的父节点,然后,调用父节点的 removeChild把自 己删掉:

// 拿到待删除节点:
var self = document.getElementById('to-be-removed');
// 拿到父节点:
var parent = self.parentElement;
// 删除:
var removed = parent.removeChild(self);
removed === self; // true

注意到删除后的节点虽然不在文档树中了,但其实它还在内存中,可以随时再次被添加到别的位置。

当你遍历一个父节点的子节点并进行删除操作时,要注意, children 属性是一个只读属性,并且它 在子节点变化时会实时更新。

例如,对于如下HTML结构:

<div id="parent">
    <p>First</p>
    <p>Second</p>
</div>

当我们用如下代码删除子节点时:

var parent = document.getElementById('parent');
parent.removeChild(parent.children[0]);
parent.removeChild(parent.children[1]); // <-- 浏览器报错

浏览器报错: parent.children[1]不是一个有效的节点。原因就在于,当 First 节点被删除 后, parent.children 的节点数量已经从2变为了1,索引 [1] 已经不存在了。 因此,删除多个节点时,要注意 children 属性时刻都在变化。

操作表单

用JavaScript操作表单和操作DOM是类似的,因为表单本身也是DOM树。

HTML表单的输入控件主要有以下几种:

  • 文本框,对应的 <input type="text"> ,用于输入文本;
  • 口令框,对应的 <input type="password">,用于输入口令;
  • 单选框,对应的 <input type="radio">,用于选择一项;
  • 复选框,对应的 <input type="checkbox">,用于选择多项;
  • 下拉框,对应的 <select>,用于选择一项;
  • 隐藏文本,对应的 <input type="hidden"> ,用户不可见,但表单提交时会把隐藏文本发送到 服务器。

获取值

如果我们获得了一个<input>节点的引用,就可以直接调用 value 获得对应的用户输入值:

// <input type="text" id="email">
var input = document.getElementById('email');
input.value; // '用户输入的值'

这种方式可以应用于 textpasswordhidden 以及 select 。但是,对于单选框和复选 框,value属性返回的永远是HTML预设的值,而我们需要获得的实际是用户是否“勾上了”选项,所 以应该用 checked判断:

// <label><input type="radio" name="weekday" id="monday" value="1">Monday</label>
// <label><input type="radio" name="weekday" id="tuesday" value="2">Tuesday</label>
var mon = document.getElementById('monday');
var tue = document.getElementById('tuesday');
mon.value; // '1'
tue.value; // '2'
mon.checked; // true或者false
tue.checked; // true或者false

设置值

设置值和获取值类似,对于 textpasswordhidden 以及 select ,直接设置 value 就可以:

// <input type="text" id="email">
var input = document.getElementById('email');
input.value = 'test@example.com'; // 文本框的内容已更新

对于单选框和复选框,设置 checkedtruefalse即可。

提交表单

JavaScript可以以两种方式来处理表单的提交(AJAX方式在后面章节介绍)。

方式一是通过 <form>元素的 submit()方法提交一个表单,例如,响应一个 buttonclick事件,在JavaScript代码中提交表单:

<!-- HTML -->
<form id="test-form">
    <input type="text" name="test">
    <button type="button" onclick="doSubmitForm()">Submit</button>
</form>
<script>
function doSubmitForm() {
    var form = document.getElementById('test-form');
    // 可以在此修改form的input...
    // 提交form:
    form.submit();
}
</script>

这种方式的缺点是扰乱了浏览器对form的正常提交。浏览器默认点击 时<button type="submit">提交表单,或者用户在最后一个输入框按回车键。因此,第二种方式是响应<form>本身的onsubmit事件,在提交form时作修改:

<!-- HTML -->
<form id="test-form" onsubmit="return checkForm()">
    <input type="text" name="test">
    <button type="submit">Submit</button>
</form>
<script>
function checkForm() {
    var form = document.getElementById('test-form');
    // 可以在此修改form的input...
    // 继续下一步:
    return true;
}
</script>

注意要 return true来告诉浏览器继续提交,如果return false ,浏览器将不会继续提交 form,这种情况通常对应用户输入有误,提示用户错误信息后终止提交form。

在检查和修改 <input>时,要充分利用<input type="hidden"> 来传递数据。

例如,很多登录表单希望用户输入用户名和口令,但是,安全考虑,提交表单时不传输明文口令,而是 口令的MD5。要想不改变用户的输入,可以利用<input type="hidden"> 实现:

<!-- HTML -->
<form id="login-form" method="post" onsubmit="return checkForm()">
    <input type="text" id="username" name="username">
    <input type="password" id="input-password">
    <input type="hidden" id="md5-password" name="password">
    <button type="submit">Submit</button>
</form>
<script>
function checkForm() {
    var input_pwd = document.getElementById('input-password');
    var md5_pwd = document.getElementById('md5-password');
    // 把用户输入的明文变为MD5:
    md5_pwd.value = md5(input_pwd.value);
    // 继续下一步:
    return true;
}
</script>

jQuery

jQuery这么流行,肯定是因为它解决了一些很重要的问题。实际上,jQuery能帮我们干这些事情:

  • 消除浏览器差异:你不需要自己写冗长的代码来针对不同的浏览器来绑定事件,编写AJAX等代码;
  • 简洁的操作DOM的方法:写 $(’#test’) 肯定比 document.getElementById(‘test’) 来得 简洁;
  • 轻松实现动画、修改CSS等各种操作。

使用jQuery只需要在页面的head引入jQuery文件即可:

JQuery官网

国内Jquery cdn

公式:$(selector).action()

  • 美元符号定义 jQuery
  • 选择符(selector)“查询"和"查找” HTML 元素
  • jQuery 的 action() 执行对元素的操作

选择器

按ID查找

如果某个DOM节点有 id 属性,利用jQuery查找如下:

// 查找<div id="abc">:
var div = $('#abc');

按tag查找

按tag查找只需要写上tag名称就可以了:

var ps = $('p'); // 返回所有<p>节点
ps.length; // 数一数页面有多少个<p>节点

按class查找

按class查找注意在class名称前加一个 . :

var a = $('.red'); // 所有节点包含`class="red"`都将返回
// 例如:
// <div class="red">...</div>
// <p class="green red">...</p>

按属性查找

一个DOM节点除了idclass 外还可以有很多属性,很多时候按属性查找会非常方便,比如在一 个表单中按属性来查找:

var email = $('[name=email]'); // 找出<??? name="email">
var passwordInput = $('[type=password]'); // 找出<??? type="password">
var a = $('[items="A B"]'); // 找出<??? items="A B">

当属性的值包含空格等特殊字符时,需要用双引号括起来。 按属性查找还可以使用前缀查找或者后缀查找:

var icons = $('[name^=icon]'); // 找出所有name属性值以icon开头的DOM
// 例如: name="icon-1", name="icon-2"
var names = $('[name$=with]'); // 找出所有name属性值以with结尾的DOM
// 例如: name="startswith", name="endswith"

操作DOM

修改Text和HTML

jQuery对象的text()html() 方法分别获取节点的文本和原始HTML文本,例如,如下的HTML 结构:

<!-- HTML结构 -->
<ul id="test-ul">
    <li class="js">JavaScript</li>
    <li name="book">Java &amp; JavaScript</li>
</ul>

分别获取文本和HTML:

$('#test-ul li[name=book]').text(); // 'Java & JavaScript'
$('#test-ul li[name=book]').html(); // 'Java &amp; JavaScript'

如何设置文本或HTML?jQuery的API设计非常巧妙:无参数调用 text()是获取文本,传入参数就变 成设置文本,HTML也是类似操作,自己动手试试:

var j1 = $('#test-ul li.js');
var j2 = $('#test-ul li[name=book]');
j1.html('<span style="color: red">JavaScript</span>');
j2.text('JavaScript & ECMAScript');

个jQuery对象可以包含0个或任意个DOM对象,它的方法实际上会作用在对应的每个DOM节点上。在 上面的例子中试试:

 $('#test-ul li').text('JS'); // 是不是两个节点都变成了JS?

修改css

jQuery对象有“批量操作”的特点,这用于修改CSS实在是太方便了。考虑下面的HTML结构:

<!-- HTML结构 -->
<ul id="test-css">
    <li class="lang dy"><span>JavaScript</span></li>
    <li class="lang"><span>Java</span></li>
    <li class="lang dy"><span>Python</span></li>
    <li class="lang"><span>Swift</span></li>
    <li class="lang dy"><span>Scheme</span></li>
</ul>

要高亮显示动态语言,调用jQuery对象的 css('name', 'value')方法,我们用一行语句实现:

$('#test-css li.dy>span').css('background-color', '#ffd351').css('color',
'red');

jQuery对象的 css() 方法可以这么用:

var div = $('#test-div');
div.css('color'); // '#000033', 获取CSS属性
div.css('color', '#336699'); // 设置CSS属性
div.css('color', ''); // 清除CSS属性

css()方法将作用于DOM节点的 style属性,具有最高优先级。如果要修改 class 属性,可 以用jQuery提供的下列方法:

var div = $('#test-div');
div.hasClass('highlight'); // false, class是否包含highlight
div.addClass('highlight'); // 添加highlight这个class
div.removeClass('highlight'); // 删除highlight这个class

显示和隐藏DOM

要隐藏一个DOM,我们可以设置CSS的 display 属性为 none ,利用 css() 方法就可以实现。 不过,要显示这个DOM就需要恢复原有的 display 属性,这就得先记下来原有的 display 属性到 底是 block 还是 inline 还是别的值。

考虑到显示和隐藏DOM元素使用非常普遍,jQuery直接提供 show()hide()方法,我们不用关 心它是如何修改display属性的,总之它能正常工作:

var a = $('a[target=_blank]');
a.hide(); // 隐藏
a.show(); // 显示

获取DOM信息

利用jQuery对象的若干方法,我们直接可以获取DOM的高宽等信息,而无需针对不同浏览器编写特定代 码:

// 浏览器可视窗口大小:
$(window).width(); // 800
$(window).height(); // 600
// HTML文档大小:
$(document).width(); // 800
$(document).height(); // 3500
// 某个div的大小:
var div = $('#test-div');
div.width(); // 600
div.height(); // 300
div.width(400); // 设置CSS属性 width: 400px,是否生效要看CSS是否有效
div.height('200px'); // 设置CSS属性 height: 200px,是否生效要看CSS是否有效

attr()removeAttr() 方法用于操作DOM节点的属性:

// <div id="test-div" name="Test" start="1">...</div>
var div = $('#test-div');
div.attr('data'); // undefined, 属性不存在
div.attr('name'); // 'Test'
div.attr('name', 'Hello'); // div的name属性变为'Hello'
div.removeAttr('name'); // 删除name属性
div.attr('name'); // undefined

操作表单

对于表单元素,jQuery对象统一提供val()方法获取和设置对应的 value属性:

/*
<input id="test-input" name="email" value="">
<select id="test-select" name="city">
<option value="BJ" selected>Beijing</option>
<option value="SH">Shanghai</option>
<option value="SZ">Shenzhen</option>
</select>
<textarea id="test-textarea">Hello</textarea>
*/
var
	input = $('#test-input'),
    select = $('#test-select'),
	textarea = $('#test-textarea');

input.val(); // 'test'
input.val('abc@example.com'); // 文本框的内容已变为abc@example.com

select.val(); // 'BJ'
select.val('SH'); // 选择框已变为Shanghai

textarea.val(); // 'Hello'
textarea.val('Hi'); // 文本区域已更新为'Hi'

可见,一个 val() 就统一了各种输入框的取值和赋值的问题。

添加DOM

要添加新的DOM节点,除了通过jQuery的 html()这种暴力方法外,还可以用 append()方法,例 如:

<div id="test-div">
    <ul>
        <li><span>JavaScript</span></li>
        <li><span>Python</span></li>
        <li><span>Swift</span></li>
    </ul>
</div

如何向列表新增一个语言?首先要拿到 <ul> 节点:

var ul = $('#test-div>ul');

然后,调用append()传入HTML片段:

ul.append('<li><span>Haskell</span></li>');

append()把DOM添加到最后, prepend()则把DOM添加到最前。

如果要把新节点插入到指定位置,例如,JavaScript和Python之间,那么,可以先定位到JavaScript,然 后用 after()方法:

var js = $('#test-div>ul>li:first-child');
js.after('<li><span>Lua</span></li>');

也就是说,同级节点可以用 after()或者before()方法。

删除节点

要删除DOM节点,拿到jQuery对象后直接调用 remove()方法就可以了。如果jQuery对象包含若干 DOM节点,实际上可以一次删除多个DOM节点:

var li = $('#test-div>ul>li');
li.remove(); // 所有<li>全被删除

事件

jQuery能够绑定的事件主要包括:

鼠标事件

  • click: 鼠标单击时触发;
  • dblclick:鼠标双击时触发;
  • mouseenter:鼠标进入时触发;
  • mouseleave: 鼠标移出时触发;
  • mousemove:鼠标在DOM内部移动时触发;
  • hover:鼠标进入和退出时触发两个函 数,相当于mouseenter加上mouseleave。

键盘事件

键盘事件仅作用在当前焦点的DOM上,通常是

  • keydown:键盘按下时触发;
  • keyup:键盘松开时触发;
  • keypress:按一次键后触发。

其他事件

  • focus:当DOM获得焦点时触发;
  • blur:当DOM失去焦点时触发;
  • change:当 、 或 的内容改变时 触发;
  • submit:当 提交时触发;
  • ready:当页面被载入并且DOM树完成初始化后触发。

初始化事件

$(function () {
	// init...
});

例子:

$(function () {
	// init...
    $('#testForm).submit(function () {
		alert('submit!');
	});
});

事件参数

有些事件,如 mousemovekeypress ,我们需要获取鼠标位置和按键的值,否则监听这些事件就 没什么意义了。所有事件都会传入 Event对象作为参数,可以从Event 对象上获取到更多的信 息:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #testMouseMoveDiv{
            width: 300px;
            height: 300px;
            border: 1px solid black;
        }
    </style>
</head>
<body>
mousemove: <span id="testMouseMoveSpan"></span>
<div id="testMouseMoveDiv">
    在此区域移动鼠标试试
</div>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<script>
$(function () {
    $('#testMouseMoveDiv').mousemove(function (e) {
        $('#testMouseMoveSpan').text('pageX = ' + e.pageX + ', pageY = '
        + e.pageY);
    });
});
</script>
</body>
</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值