dom常用相关整理

选择器

document.querySelector() //最常用(适用于各种类型)
//选择多个时用:querySelectAll()与一般的区别(如:getElementsByClassName(str))
//两者括号里面都是字符串,且前面都要加 . ,但是querySelectAll返回的是对象的集合(伪数组,用...扩展符可以把他变成数组)getElementsByClassName之类的括号里面也是字符串类型但是前面不加.#等
document.getElementById(id)	//通过元素 id 来查找元素
document.getElementsByTagName(name)	//通过标签名来查找元素
document.getElementsByClassName(name)	//通过类名来查找元素
document.getElementsByName()
document.getElementsByTagNameNS()

改变HTML元素

element.innerHTML = new html content	改变元素的内容
element.style.property = new style	//改变 HTML 元素的样式,此处可直接更改样式,也可以通过下面更改类名更改样式 
element.className=classes+' '+'red' //添加类名'red'
element.classList.add('size')  //添加类名'size'
element.classList.remove('b')   //删除类名 'b'
element.classList.replace('red','green') //注意参数一是被替换的类名,参数二是新的类名

添加和删除元素

document.createElement(element)	创建 HTML 元素
document.removeChild(element)	删除 HTML 元素
document.appendChild(element)	添加 HTML 元素
document.replaceChild(element)	替换 HTML 元素
document.write(text)	写入 HTML 输出流

查找HTML亲属元素

查父元素 dom.parentElement
查子元素们 dom.children
查兄弟 dom.nextElementSibing  /  dom.previousElementSibling

添加事件处理程序

<h1 onclick="this.innerHTML='新内容'">点击变更内容</h1>  这里不需要获取dom this指的是h1,不推荐也不经常用
<button onclick="clickHandle(1)">点击</button> 这里不需要获取dom,并且可以传递参数,点击该按钮执行函数clickHandle
document.getElementById(id).onclick = function(){code}	这里需要获取dom,且不能传参,容易出现事件覆盖现象
document.getElementById(id).addEventListener('click',function(){
    log('.........') //此种方法解决了事件覆盖问题
})

获取选中元素的css样式

/*
getComputedStyle(dom,null)[‘css属性’]
作用:1:dom对象
2:null 表示不获取子元素css
返回值:cssStyleDelecretion 样式对象集合
/
/

dom.currentStyle[‘css属性’];
/
//解决以上兼容性处理
// 兼容处理:
/
function getElement(ele) {
if (ele.currentStyle) {
return ele.currentStyle;
} else {
return getComputedStyle(ele, null);
};
};
*/

demo位置属性

document.querySelector('.box').onclick=function(ev){
    var e=ev||window.event//兼容性处理
    console.log(e.offsetX,e.offsetY); //目标元素上的坐标    原点在目标元素的左上角
    console.log(e.clientX,e.clientY); //浏览器上的坐标      原点在浏览器左上角(内容显示区,不包括导航栏)
    console.log(e.screenX,e.screenY); //屏幕上的坐标        原点在整个屏幕的左上角
    // 以上三个的原点都不一样
}
问题一:对象类型和原始类型的不同之处?函数参数是对象会发生什么问题?

DNS解析

DNS 的作用就是通过域名查询到具体的 IP。

因为 IP 存在数字和英文的组合(IPv6),很不利于人类记忆,所以就出现了域名。你可以把域名看成是某个 IP 的别名,DNS 就是去查询这个别名的真正名称是什么。

在 TCP 握手之前就已经进行了 DNS 查询,这个查询是操作系统自己做的。当你在浏览器中想访问www.google.com时,会进行一下操作:

操作系统会首先在本地缓存中查询 IP
没有的话会去系统配置的 DNS 服务器中查询
如果这时候还没得话,会直接去 DNS 根服务器查询,这一步查询会找出负责com这个一级域名的服务器
然后去该服务器查询google这个二级域名
接下来三级域名的查询其实是我们配置的,你可以给www这个域名配置一个 IP,然后还可以给别的三级域名配置一个 IP
以上介绍的是 DNS 迭代查询,还有种是递归查询,区别就是前者是由客户端去做请求,后者是由系统配置的 DNS 服务器做请求,得到结果后将数据返回给客户端。

TCP握手

接下来是 TCP 握手,应用层会下发数据给传输层,这里 TCP 协议会指明两端的端口号,然后下发给网络层。网络层中的 IP 协议会确定 IP 地址,并且指示了数据传输中如何跳转路由器。然后包会再被封装到数据链路层的数据帧结构中,最后就是物理层面的传输了。

在这一部分中,可以详细说下 TCP 的握手情况以及 TCP 的一些特性。

当 TCP 握手结束后就会进行 TLS 握手,然后就开始正式的传输数据。

TLS握手

数据在进入服务端之前,可能还会先经过负责负载均衡的服务器,它的作用就是将请求合理的分发到多台服务器上,这时假设服务端会响应一个 HTML 文件。

首先浏览器会判断状态码是什么,如果是 200 那就继续解析,如果 400 或 500 的话就会报错,如果 300 的话会进行重定向,这里会有个重定向计数器,避免过多次的重定向,超过次数也会报错。

浏览器开始解析文件

浏览器开始解析文件,如果是 gzip 格式的话会先解压一下,然后通过文件的编码格式知道该如何去解码文件。

构建 DOM 树、构建 CSSOM 树、解析JS

文件解码成功后会正式开始渲染流程,先会根据 HTML 构建 DOM 树,有 CSS 的话会去构建 CSSOM 树。如果遇到 script 标签的话,会判断是否存在 async 或者 defer ,前者会并行进行下载并执行 JS,后者会先下载文件,然后等待 HTML 解析完成后顺序执行。

如果以上都没有,就会阻塞住渲染流程直到 JS 执行完毕。遇到文件下载的会去下载文件,这里如果使用 HTTP/2 协议的话会极大的提高多图的下载效率。

生成 Render 树

CSSOM 树和 DOM 树构建完成后会开始生成 Render 树,这一步就是确定页面元素的布局、样式等等诸多方面的东西

调用 GPU 绘制,合成图层,将内容显示在屏幕上了

在生成 Render 树的过程中,浏览器就开始调用 GPU 绘制,合成图层,将内容显示在屏幕上了。

这一部分就是渲染原理中讲解到的内容,可以详细的说明下这一过程。并且在下载文件时,也可以说下通过 HTTP/2 协议可以解决队头阻塞的问题。
# 专题

## 高阶函数

## 闭包

## 1防抖

## 2节流

## 数组去重

## 求数组最大值和最小值

## 数组扁平化

## 数据类型判断

## 数据拷贝

## 从0实现jquery的dom操作

## 从0 实现jquery 的extend()

## 跟着underscore.js在数组汇总查找元素

## 判断两个对象是否相等

## 函数柯理化

## 偏函数

## 惰性函数

## 函数组合

## 函数记忆

## 递归

## 解读V8排序袁爱民

问题一:进程与线程区别?JS 单线程带来的好处?
相信大家经常会听到 JS 是单线程执行的,但是你是否疑惑过什么是线程?

讲到线程,那么肯定也得说一下进程。本质上来说,两个名词都是 CPU工作时间片的一个描述。

进程描述了 CPU 在运行指令及加载和保存上下文所需的时间,放在应用上来说就代表了一个程序。线程是进程中的更小单位,描述了执行一段指令所需的时间。

把这些概念拿到浏览器中来说,当你打开一个 Tab 页时,其实就是创建了一个进程,一个进程中可以有多个线程,比如渲染线程、JS 引擎线程、HTTP 请求线程等等。当你发起一个请求时,其实就是创建了一个线程,当请求结束后,该线程可能就会被销毁。

上文说到了 JS 引擎线程和渲染线程,大家应该都知道,在 JS 运行的时候可能会阻止 UI 渲染,这说明了两个线程是互斥的。这其中的原因是因为 JS 可以修改 DOM,如果在 JS 执行的时候 UI 线程还在工作,就可能导致不能安全的渲染 UI。这其实也是一个单线程的好处,得益于 JS 是单线程运行的,可以达到节省内存,节约上下文切换时间,没有锁的问题的好处。当然前面两点在服务端中更容易体现,对于锁的问题,形象的来说就是当我读取一个数字 15 的时候,同时有两个操作对数字进行了加减,这时候结果就出现了错误。解决这个问题也不难,只需要在读取的时候加锁,直到读取完毕之前都不能进行写入操作。

执行上下文栈

js代码执行顺序是什么,大部分人都知道同步执行

var foo = function(){
            console.log('foo1');
        }
        foo(); // foo1
        var foo = function(){
            console.log('foo2');
        }
        foo() // foo2

然后看以下下面代码


        function foo(){
            console.log('foo1');0
        }

        foo();// foo2
        function foo(){
            console.log('foo2');
        }
        foo() // foo2

js 引擎 执行代码是 一段一段分析执行;不是一行一行执行的 当一段代码执行完毕后, 会进行一个准备工作,比如:第一个例子,变量提升,第二个例子中, 函数声明提升
准备工作:变量提升,函数提升

问题:段 是如何划分的?
准备工作是什么时候进行的呢?

可执行代码

这就要说到 JavaScript 的可执行代码(executable code)的类型有哪些了?

其实很简单,就三种,全局代码、函数代码、eval代码。

举个例子,当执行到一个函数的时候,就会进行准备工作,这里的“准备工作”,让我们用个更专业一点的说法,就叫做"执行上下文(00context)"。

执行上下文栈

接下来问题来了,我们写的函数多了去了,如何管理创建的那么多执行上下文呢?

所以 JavaScript 引擎创建了执行上下文栈(Execution context stack,ECS)管理执行上下文

为了模拟执行上下文栈的行为,让我们定义执行上下文栈是一个数组

ECStack = [];+

假设当 JavaScript 开始要解释执行代码的时候,最先遇到的就是全局代码,所以初始化的时候首先就会向执行上下文栈添加一个全局执行上下文,我们用 globalContext 表示它,并且只有当整个应用程序结束的时候,ECStack 才会被清空,所以程序结束之前, ECStack 最底部永远有个 globalContext:

// 模拟将全局执行上下文添加到执行上下文栈中
ECStack = [
    globalContext
];

现在 js 引擎 遇到下面的这段代码了:

function foo3() {
    console.log('foo3')
}

function foo2() {
    foo3();
}

function foo1() {
    foo2();
}

foo1();

执行一个函数的时候,就会创建一个执行上下文,并且添加执行上下文栈,当函数执行完毕的时候,就会将函数的执行上下文从栈中弹出。知道了这样的工作原理,让我们来看看js引擎如何处理上面这段代码:


// 模拟js引擎执行代码

// foo1()
ECStack.push(<foo1> functionContext);

// foo1中竟然调用了foo2,还要创建foo2的执行上下文
ECStack.push(<foo2> functionContext);

// foo2还调用了foo3!创建 foo3执行上下文
ECStack.push(<foo3> functionContext);
// ECStack= [globalContext,foo1<functionCountext>,foo2<functionCountext>,foo3<funcrtionCountext>]

// foo3执行完毕 foo3执行上下文销毁
ECStack.pop(); 
// ECStack= [globalContext,foo1<functionCountext>,foo2<functionCountext>]

// foo2执行完毕 foo2执行上下文销毁 
ECStack.pop(); 
// ECStack= [globalContext,foo1<functionCountext>]

// foo1执行完毕,foo1执行上下文销毁
ECStack.pop();
// ECStack= [globalContext]


// javascript接着执行下面的代码,但是ECStack底层永远有个globalContext
// 关闭浏览器 关闭应用程序
// ECStack.pop()
// ECStack = []

执行上下文

1: 作用域链 scope
2: 变量对象 GO AO  (预编译)
3: this 
执行上下文一旦销毁,以上3个内容都销毁

解答思考题

好啦,现在我们已经了解了执行上下文栈是如何处理执行上下文的,所以让我们看看上篇文章 《JavaScript深入之词法作用域和动态作用域》
最后的问题:

var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f();
}
checkscope();
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f;
}
checkscope()();

两段代码执行的结果一样,但是两段代码究竟有哪些不同呢?

答案就是执行上下文栈的变化不一样。

让我们模拟第一段代码:

ECStack.push(<checkscope> functionContext);
ECStack.push(<f> functionContext);
ECStack.pop();
ECStack.pop();

让我们模拟第二段代码:

ECStack.push(<checkscope> functionContext);
ECStack.pop();
ECStack.push(<f> functionContext);
ECStack.pop();

是不是有些不同呢?

当然了,这样概括的回答执行上下文栈的变化不同,是不是依然有一种意犹未尽的感觉呢,为了更详细讲解两个函数执行上的区别,我们需要探究一下执行上下文到底包含了哪些内容,所以欢迎阅读下一篇《JavaScript深入之变量对象》。

下一篇文章

《JavaScript深入之变量对象》

深入系列

JavaScript深入系列目录地址

JavaScript深入系列预计写十五篇左右,旨在帮大家捋顺JavaScript底层知识,重点讲解如原型、作用域、执行上下文、变量对象、this、闭包、按值传递、call、apply、bind、new、继承等难点概念。

如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎star,对作者也是一种鼓励。

js代码都是同步执行的,有序的放入到执行栈中。如果遇到异步代码,会先挂起任务队列中,当执行栈为空时候,将EventLop需要的执行的时候,从任务队列中取出,放入执行栈中执行。执行结束推出执行栈。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是HTML DOM常用的一些方法: 1.ById(id):通过元素的id属性获取元素。 2. getElementsByTagName(tagName):通过元素的标签名获取元素集合。 3. getElementsByClassName(className):通过元素的类名获取元素集合。 4. querySelector(selector):通过CSS选择器获取匹配的第一个元素。 5. querySelectorAll(selector):通过CSS选择器获取所有匹配的元素。 6. createElement(tagName):创建一个新的元素节点。 7. createTextNode(text):创建一个包含指定文本内容的文本节点。 8. appendChild(node):将一个节点添加为另一个节点的子节点。 9. removeChild(node):从父节点中移除指定的子节点。 10. replaceChild(newNode, oldNode):用一个新节点替换父节点中的指定子节点。 11. cloneNode(deep):克隆一个节点。 12. parentNode:获取当前节点的父节点。 13. childNodes:获取当前节点的所有子节点集合。 14. firstChild:获取当前节点的第一个子节点。 15. lastChild:获取当前节点的最后一个子节点。 16. nextSibling:获取当前节点的下一个兄弟节点。 17. previousSibling:获取当前节点的上一个兄弟节点。 18. innerHTML:获取或设置当前元素的HTML内容。 19. value:获取或设置表单元素的值。 20. style:获取或设置元素的样式属性。 这只是一小部分常用方法,HTML DOM还有很多其他方法和属性可供使用。可以根据具体需求查阅相关文档或参考教程来了解更多方法和属性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值