JavaScript DOM编程艺术学习笔记(一)

这是我参与更文挑战的第11天,活动详情查看:更文挑战

原创声明

文章曾被多个网站转载,特此声明一下,图灵社区原文和掘金本文,均为本人创作,其余出处为他人转载。
本篇为学习《JavaScript DOM编程艺术》的学习笔记。

前言

在JavaScript引擎正式编译之前,会进行一次预编译,在这个过程中,会将变量声明及函数声明提升至当前作用域的最顶端,其后才进行接下来的处理。

变量提升

未使用块级作用域:

源代码:

console.log(msg);// undefined
var msg = "This is a message";
console.log(msg);// This is a message

function fn () {
  console.log(hello); // undefined
  var hello = 'hello world';
  console.log(hello); // hello world
}
fn();
复制代码

JavaScript解析器的解析流程:

var msg;// 变量提升,全局作用域范围内,此时只是声明,并没有赋值
console.log(msg);// undefined
 msg = "This is a message";// 此时才赋值
console.log(msg);// 打印出This is a message

function fn () {
	var hello;// 变量提升,函数作用域范围内,此时只是声明,并没有赋值
  console.log(hello); // undefined
  hello = 'hello world';// 此时才赋值
  console.log(hello); // hello world
}
fn();
复制代码

ES5只有全局作用域和函数作用域,而ES6开始提供了块级作用域。使用ES6语法的let创建的变量和const语法创建的常量,均不存在变量提升。

使用块级作用域:

console.log(msg);//Uncaught ReferenceErrord
let msg = "This is a message";//没有被执行
console.log(msg);//没有被执行

function fn () {
  console.log(hello); //Uncaught ReferenceErrord
  let hello = 'hello world'; //没有被执行
  console.log(hello); //没有被执行
}
fn();
复制代码

IIFE与块级作用域

一般的JavaScript函数有三种写法。

1.函数关键字,也叫函数声明语句写法

function foo(){}; foo();
复制代码

2.函数字面量,也叫函数表达式写法

var foo = function(){}; foo();
复制代码

3.funtion()构造函数

var foo = new function(): foo();
复制代码

有时需要在定义函数之后,立即调用该函数。这种函数就叫做立即执行函数,全称为立即调用的函数表达式IIFE(Imdiately Invoked Function Expression)。 通过立即调用的函数表达式,能够实现块级作用域的效果。

JavaScript引擎规定,如果function关键字出现在行首,一律解释成函数声明语句,而且声明语句必须要有一个函数名。所以如下的代码demo会报错。

function () {}; //Uncaught SyntaxError: Unexpected token (
复制代码

正确的写法是给函数声明语句提供一个函数名。

function foo() {}; //undefined
复制代码

接下来将函数声明语句与JavaScript分组操作符进行组合,看上去这样的组合好像并没有什么意义,并且会抛出一个错误:

function foo() {} (); //Uncaught SyntaxError: Unexpected token )
复制代码

错误在于JavaScript分组操作符需要指定一个值,不能为空。

正确的组合写法:

function foo() {} (0);//0
复制代码

function foo() {}; (0); //0 两种写法等价。
复制代码

这样也仅仅是实现了函数声明语句与不报错的分组操作符的组合。

所以需要将函数声明语句改成函数表达式写法,将function使用分组操作符进行组合。这样就不需要再指定一个函数名。这个表达式将会在加载网页时立即执行,而不需要单独调用函数。执行后,函数内代码块声明的变量将只在局部作用域内有效。无法被外层访问到。

(function () {} () );
复制代码

或者

(function () {}) ();
复制代码

在ECMAScript6中,由于块级作用域的出现,实际上使得获得广泛应用的立即执行函数表达式(IIFE)不再必要了。

// IIFE 写法 
(function () { var tmp = 0; }());



// 块级作用域写法
{ let tmp = 0; }
复制代码

函数提升

函数提升与变量提升效果一致,但JavaScript只有函数声明语句才存在函数提升.

源代码:

console.log(msg1); // function msg1() {};
console.log(msg2); // undefined
function msg1() {}
var msg2 = function() {}
复制代码

JavaScript解析器的解析流程:

function msg1() {}; // 函数提升,整个代码块提升到文件的最开始
console.log(msg1);
console.log(msg2);
var msg2 = function() {}
复制代码

参考来源:

深入理解闭包系列第三篇——IIFE

ECMAScript 6 入门

任务一:零基础JavaScript编码(一)

DOM节点

节点类型

DOM节点总共有三种类型:

  • 元素节点:HTML文件中所有元素,如p标签,ul标签。
  • 文本节点:元素节点中的文本内容,如p标签中的hello world。
  • 属性节点:标签中的属性key和value对,如img标签的src属性。

获取元素节点

通过DOM获取元素节点通常用3种DOM方法:

//获取ID为divFirst的元素节点对象

var divFirst =document.getElementById('divFirst');

//获取class为message的所有元素节点对象数组

var message = document.getElementsByClassName('message');

//通过getElementsByClassName获取的元素节点通常为值组成的数组集合,可以通过length获取数组长度
var messageLength = message.length;
//遍历所有class为message的元素节点
for(let i = 0; i < messageLength - 1;i++){
  document.write(message[i]);
}

//获取所有li标签的元素节点对象数组
var li = document.getElementsByTagName('li');
//通过getElementsByTagName获取的元素节点通常为值组成的数组集合,可以通过length获取数组长度
var liLength = li.length;
//遍历所有li的元素节点
for(let i = 0; i < liLength - 1;i++){
  document.write(li[i]);
}
复制代码

而新DOM标准效仿jQuery,依照CSS选择器提供了一套新的DOM获取元素节点的方法,它能做到的不仅仅是获取id,class以及元素标签,还能以各种CSS选择器的形式进行元素筛选的选取。

//获取ID为divFirst的元素节点对象
var divFirst = document.querySelector('#divFirst');
//获取Class为message的首个元素节点对象
var message = document.querySelector('.message');
//获取li标签的首个元素节点对象
var li = document.querySelector('li');

//获取class为message的所有元素节点对象数组
var message = document.querySelectorAll('.message');
var messageLength = message.length;
for(let i = 0; i < messageLength - 1;i++){
  document.write(message[i]);
}
//获取所有li标签的元素节点对象数组
var li = document.querySelectorAll('li');
var liLength = li.length;
for(let i = 0; i < liLength - 1;i++){
  document.write(li[i]);
}

//还能依照其它CSS选择器进行元素节点的获取
复制代码

获取和修改属性节点

//获取id为message的title属性值
var messageTitle  = document.querySelector('#message').getAttribute('title');
//如果title存在,则返回title的文本值,如果不存在,则返回null
document.write(messageTitle);

//修改或设置id为message的title属性值
var messageTitle  = document.querySelector('#message').setAttribute('title','This is a message');
//如果title存在,则修改title的文本值,如果不存在,则创建并设置title的文本值
document.write(messageTitle);
```
# 获取所有子节点
在一颗滑稽树(不对~节点树)上,childNodes属性可以用来获取任何一个元素的所有子元素,它是一个包含这个元素所有子元素的数组:
```javascript
//选取body元素下所有子节点
var body_element = document.getElementsByTagName("body")[0].childNodes;
//获取数组长度
var body_element_length = body_element.length;
//打印数组长度
alert(body_element_length);
复制代码

获取单个类型的所有子节点

通过childNodes属性获取到的节点子元素个数极为庞大,其实是因为文档的节点类型并非只有元素节点,它还包括一开始说到的属性节点和文本节点。

  • 元素节点的nodeType属性值是1
  • 属性节点的nodeType属性值是2
  • 文本节点的nodeType属性值是3

通过这个规则,获取body元素内所有元素节点的方式可以这样做:

//选取body元素的所有子节点
var body_element = document.getElementsByTagName("body")[0].childNodes;
//获取数组长度
var body_element_length = body_element.length;
//获取单个类型的所有子节点
for(let i = 0; i < body_element.length;i++){
	if(body_element.nodeType == 1){
		document.write(body_element[i]);
	}
}
复制代码

查看/修改文本节点属性值

假设有一个id为hello的p标签,含有文本hello world,利用nodeValue属性,能够获取或修改该标签的文本。

var pElement = document.querySelector('#hello').nodeValue;
//查看该文本节点的值
document.write(pElement);
复制代码

firstCHild和lastChild属性

firstChild和lastChild分别代表childNodes的首个节点和末尾节点,可说是childNodes的语义化属性。

//firstChild等同于node.childNodes[0]
var body_element = document.getElementsByTagName("body")[0].childNodes[0];
var body_element_firstChild = document.getElementsByTagName("body")[0].firstChild;
//lastCHild等同于node.childNodes[node.childNodes.length-1]
var body_element = document.getElementsByTagName("body")[0].childNodes[body_element.length-1];
var body_element_firstChild = document.getElementsByTagName("body")[0].lastChild;
复制代码

平稳退化

平稳退化的概念是在访问者访问不支持JavaScript的浏览器,仍然能过正常顺利地浏览你网站的基本功能。在2017年,前端离不开javascript的今天,可能听起来很荒谬,不过,无论是对特殊设备的访问者还是蜘蛛爬虫而言,平稳退化都不是一个过时的概念。

渐进增强

所谓渐进增强,就是用一些额外的信息层去包裹原始数据,按照“渐进增强”的原则创建的网页,几乎都符合“平稳退化原则”,简而言之,就是尽可能去语义化文本标签。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享