JS高级编程

1.JavaScript的构成

虽然 JavaScript 和 ECMAScript 通常都被人们用来表达相同的含义,但 JavaScript 的含义却比 ECMA-262 中规定的要多得多。没错,一个完整的 JavaScript 实现应该由下列三个不同的部分组成。

  • 核心(ECMAScript)

  • 文档对象模型(DOM)--document Object Module

  • 浏览器对象模型(BOM)--Browser Object Module

ECMAScript:是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers Association)通过ECMA-262标准化的脚本程序设计语言。这种语言在万维网上应用广泛,它往往被称为JavaScript或JScript,但实际上后两者是ECMA-262标准的实现和扩展

BOM: Browse Object Model,提供与浏览器交互的方法和接口

DOM: Document Object Model,提供访问和操作网页内容的方法和接口

2.JavaScript的特点

JS 运行在客户端--浏览器

JS 解释器,负责js 的执行; ​ V8 引擎负责js 的执行,把js 代码编译成机器码; ​ JS 定位成弱类型,脚本语言:在运行的时候,不需要编译。

(1) JavaScript是一种脚本编程语言

这里要解释一下什么是脚本语言,也许很多读者之前已经接触过脚本语言,其实脚本语言是一种简单的程序,它是由一些ASCII字符构成,可以直接用记事本等文本编辑器编写,事先也不用编译,只需要利用解释器就可以解释执行。

前面已经介绍过JavaScript是一种脚本语言,是采用小程序段的方式实现编程。正如其它脚本语言一样,JavaScript也是一种解释性语言,它提供了一个容易的开发过程。JavaScript的基本结构形式与其它高级语言类似(如C、C++、VB、Delphi等),但它与这些高级语言不同的是,其它高级语言需要先进行编译然后才能被执行,JavaScript则是在程序运行过程中一条一条被解释执行。JavaScript与HTML结合在一起,极大地方便了用户的使用操作。

(2) JavaScript是面向对象的语言

JavaScript是一种面向对象的语言,那就是说,它本身也可以创建对象,以及调用对象的操作。因此,JavaScript的诸多功能可以来自于脚本环境中各种对象的调用。

(3) JavaScript的简单性

之所以说JavaScript是简单的,首先是因为它是一种基于Java的基本语句和控制流之上的简单而紧凑的设计,这对于更进一步学习Java是一个非常好的过渡,其次是因为它的所有变量都是弱类型,并且都没有像其它需要编译的高级语言那样使用严格的数据类型。

(4) JavaScrip的安全性

JavaScrip就像Java一样是一种非常安全的语言,它不允许访问本地的硬盘,并且不允许把数据存入到服务器上,还不允许对网络文档进行修改和删除,只允许通过浏览器实现信息浏览和动态交互,这样确保了对数据的安全化操作。

(5) JavaScript的动态性

之所以说JavaScript是动态的,是因为它可以直接对用户或客户的输入操作做出响应,而不必经过web服务器或web服务器程序。

JavaScript对用户的响应是采用事件驱动的方式进行的。简单地说,事件驱动是指在页面中执行了某种操作后产生相应的动作,例如,按下鼠标、选择菜单以及移动窗口等都可以被视为事件,当事件发生后,就会有相应的事件响应该事件。

(6) JavaScript的跨平台性

JavaScript同Java一样是与操作环境无关的,它只依赖于浏览器,只要客户的计算机浏览器支持JavaScrip,它就可以被正确解释执行。从而实现一次编写,到处运行。

3.事件

事件三要素:事件源  事件  事件处理函数

        事件源:标签

        事件:click  dblclick  mousemove...

        事件处理函数: 干什么

        事件源.on事件 = 事件处理函数

(1)标签的获取:

通过类名获取:document.getElementsByClassName("类名")

通过id获取:document.getElementById("id名")

通过标签名获取document.getElementsByTagName("标签名")

通过name属性获取:document.getElementsByName("name属性值")

通过css选择器获取:document.querySelector("css选择器")

(2)标签属性的相关操作:

<div class="box box1">box1</div>

<form>

         账号:<input type="text" name="account">

         密码:<input type="text" name="pwd">

         <input type="submit">

     </form>

     <img src="https://img1.baidu.com/it/u=917108111,1107211158&fm=253&fmt=auto&app=138&f=JPEG?w=650&h=274" alt="">

<script>

        let box1 = document.querySelector(".box1");

        box1.setAttribute("id","mybox1");

        box1.setAttribute("newAttr","newAttr");

        box1.setAttribute("class",box1.getAttribute("class")+" newclass");

        box1.removeAttribute("newAttr");

        // 对标签属性直接进行操作: 标签.属性 = 属性值;

        box1.id = "newid";

        document.querySelector("img").src = "https://img1.baidu.com/it/u=1294011985,3019794183&fm=253&fmt=auto&app=138&f=JPEG?w=631&h=405";

        document.querySelectorAll('input')[0].value = "123456";

        console.log(document.querySelector("img").src);

        console.log(document.querySelectorAll('input')[0].value);

        // 注意:类名不能直接操作(class属性不能直接操作)

        // box1.class = "myNewclass";

    </script>

(3)标签类名的相关操作:

<div class="box box1" id="mybox1">box1</div>

    <div class="box box2">box2</div>

    <div class="box box3">box3</div>

    <div class="box box4">box4</div>

    <span>我是span</span>

    <form>

        账号:<input type="text" name="account">

        密码:<input type="text" name="pwd">

        <input type="submit">

    </form>

    <script>

        let box2 = document.querySelector('.box2');

        console.dir(box2);

        console.log(box2.className);

        console.log(box2.classList);

        // 类名的添加

        box2.classList.add("newclass");

        box2.classList.add("newclass");

        // 判断标签是否包含某个类名

        console.log(box2.classList.contains("newclass123"));

        // 类名的移除

        box2.classList.remove("newclass");

        // 判断某个标签是否拥有某个类名,有就删除,没有就添加

        box2.classList.toggle("box");

        // 标签类名的替换

        // box2.classList.replace("box2","bbb");

    </script>

(4)标签内容的获取和修改:

 <div class="box box1" id="mybox1">box1</div>

    <div class="box box2">box2</div>

    <div class="box box3">box3</div>

    <div class="box box4">box4</div>

    <span>我是span</span>

    <form>

        账号:<input type="text" name="account">

        密码:<input type="text" name="pwd">

        <input type="submit">

    </form>

    <script>

        let box1 = document.getElementById('mybox1');

        console.dir(box1);

        box1.onclick = function(){

            // console.log(document.getElementsByTagName('span'));

            document.getElementsByTagName('span')[0].classList.toggle("active");

        }

        console.log(box1.innerHTML);

        console.log(box1.innerText);

        console.log(box1.outerHTML);

        // 修改

        // box1.innerHTML = `<h2>修改后的内容</h2>`;

        box1.innerText = `<h2>修改后的内容</h2>`;

    </script>

(5)标签的删除 、复制和替换:

 <div class="box box1" id="mybox1">box1</div>

    <div class="box box2">box2</div>

    <div class="box box3">

        <p>我是box3里面的p</p>

    </div>

    <div class="box box4">box4</div>

    <span>我是span</span>

    <ul>

        <li>列表1</li>

        <li>列表2</li>

        <li>列表3</li>

    </ul>

    <form>

        账号:<input type="text" name="account">

        密码:<input type="text" name="pwd">

        <input type="submit">

    </form>

    <script>

        // 标签的删除

        let box2 = document.querySelector('.box2');

        // box2.remove();

        let form = document.querySelector('form');

        let account = document.getElementsByName('account')[0];

        console.log(form,account);

        // form.removeChild(account);

        console.log("=======================");

        // 标签的克隆

        let ul = document.querySelector('ul');

        // console.log(ul.cloneNode());

        console.log(ul.cloneNode(true));

        let box1 = document.querySelector('.box1');

        box1.append(ul);

        console.log("=======================");

        // 替换

        let box3 = document.querySelector('.box3');

        let img = document.createElement("img");

        img.src = 'https://img1.baidu.com/it/u=2645923382,3836110976&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500'

        // box3.replaceChild(newNode,oldNode);

        box3.replaceChild(img,document.querySelector('.box3 p'));

    </script>

4.事件的绑定与移除

    <div class="box1">box1</div>

    <!-- <div class="box2" οnclick="box2()">box2</div> -->

    <div class="box3">box3</div>

    <!-- <div class="box4" οnclick="alert('点了box4一下')">box4</div> -->

    <script>

        function box2(){

            alert("点了box2一下");

        }

        var box1 = document.querySelector('.box1');

        // 事件的绑定

        // box1.onclick = function(){

        //     alert("点了box1一下");

        // }

        // 事件的移除

        // box1.onclick = null;

        // 事件的绑定: box1.addEventListener(事件,事件处理函数)

        // box1.addEventListener('click',box1_click);

        // 事件的移除: box1.removeEventListener(事件,事件处理函数)

        // box1.removeEventListener('click',box1_click);

        function box1_click(){

            alert("点了box1一下");

        }

       

        // 事件的绑定:box1.attachEvent(on事件,事件处理函数);

        // box1.attachEvent('onclick',box1_click);

        // 事件的移除:box1.detachEvent(on事件,事件处理函数);

        // box1.detachEvent('onclick',box1_click);

        // 事件绑定兼容性处理的封装

        function addEvent(el,ev,fn){

            if(el.addEventListener){

                el.addEventListener(ev,fn);

            }else if(el.attachEvent){

                el.attachEvent('on'+ev,fn);

            }else{

                el['on'+ev] = fn;

            }

        }

        addEvent(box1,'click',box1_click);

        // 事件移除兼容性处理的封装

        function removeEvent(el,ev,fn){

            if(el.removeEventListener){

                el.removeEventListener(ev,fn);

            }else if(el.detachEvent){

                el.detachEvent('on'+ev,fn);

            }else{

                el['on'+ev] = null;

            }

        }

    </script>

5.事件三阶段和事件委托

事件三阶段:捕获、目标、冒泡(先捕获、再目标、最后冒泡)

事件委托:又叫事件代理

        原理:利用了事件冒泡

        事件委托就是当多个标签需要绑定相同的一个事件的时候,就可以把这个事件委托给他们的某个祖先

 <ul>

        <li>列表1</li>

        <li>列表2</li>

        <li>列表3</li>

        <li>列表4</li>

    </ul>

<script>

        let ul = document.querySelector('ul');

        ul.addEventListener('click',function(){

            // console.log(this);

            console.log(event.target);

        })

    </script>

6.重绘和回流

        1.先进行域名解析

        2.进行http请求,三次握手四次挥手

        3.加载解析html:代码就是从上往下一行一行的执行,在执行的过程中,会解析html标签创建一个DOM树,

        解析css创建CSSOM,将DOM树和CSSOM结合,合并成一个Render Tree(渲染树),根据渲染树,去布局绘制并显示。

       

        浏览器的渲染过程:

        1.解析html创建DOM树

        2.解析css创建CSSOM  (css rule true  css规则树)

        3.将DOM树和CSSOM结合,合并成一个Render Tree(渲染树)

        4.根据渲染树,去布局绘制并显示

        DOM    CSSOM    Render Tree

        重绘:

        当元素样式的改变不会影响布局时,浏览器将会使用重绘对元素进行更新,此时只需要UI层面的重新像素绘制,所以损耗较少

        常见的重绘操作:

        改变元素的颜色、改变元素的背景颜色等

        回流(重排):

        当元素的尺寸、结构发生改变或者出发某些属性时,浏览器会重新计算渲染页面内,发生回流

        比如让标签隐藏或者改变标签的宽高、还有就是通过js往页面中添加DOM元素以及通过js获取元素的尺寸大小或者偏移量

        重绘不一定会引起回流,但是回流一定会引起重绘


 

        常见的回流操作:

        DOM的添加和删除;

        页面的加载;

        元素尺寸改变——边距、填充、边框、宽度和高度;

        元素位置的改变;

        内容变化,比如用户在input框中输入文字;

        浏览器窗口尺寸改变——resize事件发生时;

        获取某些属性:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、

        scrollHeight、 clientTop、clientLeft、clientWidth、clientHeight。(浏览器为了返回最精确的值,需要flush队列,

        因为队列中可能会有影响到这些值的操作)


 

        减少重绘与回流:

        css

        使用 transform 替代 top、left

        使用 visibility 替换 display: none ,因为前者只会引起重绘,后者改变了布局会引发回流。

        避免使用table布局,可能很小的一个小改动会造成整个 table 的重新布局。

        避免设置多层内联样式,CSS 选择符从右往左匹配查找,避免节点层级过多。

        js

        避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。

        避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。

        避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。

        对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。

         避免触发同步布局

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值