JavaScript DOM部分基础知识学习笔记(4)

1 篇文章 0 订阅
1 篇文章 0 订阅

目录

JavaScript_浏览器环境概述(BOM)

代码嵌入网页的方法

加载使用的协议

JavaScript_script元素工作原理

defer 属性

async 属性

JavaScript_回流和重绘

什么是回流和重绘

JavaScript_定时器之setTimeout

JavaScript_定时器之setInterval

JavaScript_防抖(debounce)

JavaScript_节流(throttle)

 JavaScript_window对象_属性

window.screenX,window.screenY

window.innerHeight,window.innerWidth

 window.outerHeight,window.outerWidth

window.scrollX,window.scrollY

JavaScript_window对象_方法

window.alert(),window.prompt(),window.confirm()

window.open()

JavaScript_Navigator对象

JavaScript_Screen对象

Screen.height

Screen.width

Screen.availHeight

Screen.availWidth

Screen.pixelDepth

Screen.orientation

JavaScript_History对象

History.back()

History.forward()

History.go()

 JavaScript_Cookie对象

 JavaScript_Cookie属性

Expires

Max-Age

Domain

Path

Secure

HttpOnly

JavaScript_封装Cookie(在服务器运行)

JavaScript_call_apply_bind函数


JavaScript_浏览器环境概述(BOM)

JavaScript 是浏览器的内置脚本语言,一旦网页内嵌了 JavaScript 脚本,浏览器加载网页,就会去执行脚本,从而达到操作浏览器的目的,实现网页的各种动态效果

代码嵌入网页的方法

<script>元素直接嵌入代码。

<script>
  var x = 1 + 5;
  console.log(x);
</script>

<script>标签加载外部脚本

<script src="https://www.example.com/script.js"></script>

加载使用的协议

http协议

<script src="http://example.js"></script>

https协议

<script src="https://example.js"></script>

但是有时我们会希望,根据页面本身的协议来决定加载协议,这时可以采用下面的写法

<script src="//example.js"></script>

JavaScript_script元素工作原理

工作原理

浏览器加载 JavaScript 脚本,主要通过<script>元素完成。正常的网页加载流程是这样的

  1. 浏览器一边下载 HTML 网页,一边开始解析。也就是说,不等到下载完,就开始解析
  2. 解析过程中,浏览器发现<script>元素,就暂停解析,把网页渲染的控制权转交给 JavaScript 引擎
  3. 如果<script>元素引用了外部脚本,就下载该脚本再执行,否则就直接执行代码
  4. JavaScript 引擎执行完毕,控制权交还渲染引擎,恢复往下解析 HTML 网页

加载外部脚本时,浏览器会暂停页面渲染,等待脚本下载并执行完成后,再继续渲染。原因是 JavaScript 代码可以修改 DOM,所以必须把控制权让给它,否则会导致复杂的线程竞赛的问题。

如果外部脚本加载时间很长(一直无法完成下载),那么浏览器就会一直等待脚本下载完成,造成网页长时间失去响应,浏览器就会呈现“假死”状态,这被称为“阻塞效应”。

为了避免这种情况,较好的做法是将<script>标签都放在页面底部,而不是头部。这样即使遇到脚本失去响应,网页主体的渲染也已经完成了,用户至少可以看到内容,而不是一张空白的页面。

defer 属性

为了解决脚本文件下载阻塞网页渲染的问题,一个方法是对<script>元素加入defer属性。它的作用是延迟脚本的执行,等到 DOM 加载生成后,再执行脚本

<script src="./js/index.js" defer></script>

defer属性的运行流程如下

  1. 浏览器开始解析 HTML 网页
  2. 解析过程中,发现带有defer属性的<script>元素
  3. 浏览器继续往下解析 HTML 网页,同时并行下载<script>元素加载的外部脚本
  4. 浏览器完成解析 HTML 网页,此时再回过头执行已经下载完成的脚本

 有了defer属性,浏览器下载脚本文件的时候,不会阻塞页面渲染

async 属性

解决“阻塞效应”的另一个方法是对<script>元素加入async属性

<script src="./js/index1.js" async></script>
<script src="./js/index.js" async></script>

async属性的作用是,使用另一个进程下载脚本,下载时不会阻塞渲染

  1. 浏览器开始解析 HTML 网页
  2. 解析过程中,发现带有async属性的script标签
  3. 浏览器继续往下解析 HTML 网页,同时并行下载<script>标签中的外部脚本
  4. 脚本下载完成,浏览器暂停解析 HTML 网页,开始执行下载的脚本
  5. 脚本执行完毕,浏览器恢复解析 HTML 网页

async属性可以保证脚本下载的同时,浏览器继续渲染。需要注意的是,一旦采用这个属性,就无法保证脚本的执行顺序。哪个脚本先下载结束,就先执行那个脚本

一般来说,如果脚本之间没有依赖关系,就使用async属性,如果脚本之间有依赖关系,就使用defer属性。如果同时使用asyncdefer属性,后者不起作用,浏览器行为由async属性决定

JavaScript_回流和重绘

渲染树转换为网页布局,称为“布局流”(flow);布局显示到页面的这个过程,称为“绘制”(paint)。它们都具有阻塞效应,并且会耗费很多时间和计算资源。

页面生成以后,脚本操作和样式表操作,都会触发“回流”(reflow)和“重绘”(repaint)。

什么是回流和重绘

回流:当节点树中的一部分因为元素的规模尺寸,布局,隐藏等改变而需要重新构建

重绘:当节点数中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的

温馨提示

回流和重绘并不一定一起发生,回流必然导致重绘,重绘不一定需要回流。比如改变元素颜色,只会导致重绘,而不会导致回流;改变元素的布局,则会导致重绘和回流

 什么时候会造成回流和重绘

回流

  1. 页面初始加载
  2. 改变字体,元素尺寸(width,height,border,position),改变元素内容
  3. 添加或删除元素,如果元素本身被display:none会回流,visibility:hidden则会发生重绘
  4. 定位为fixed的元素,滚动条拖动时会回流
  5. 调整窗口大小

重绘

colorborder-stylevisibilitybackground
text-decorationbackgtound-imagebackground-repeatbackground-position
outline-coloroutlineoutline-styleborder-radius
outline-widthbox-shadowbackground-size

 优化技巧

  1. 读取 DOM 或者写入 DOM,尽量写在一起,不要混杂。不要读取一个 DOM 节点,然后立刻写入,接着再读取一个 DOM 节点
  2. 缓存 DOM 信息
  3. 不要一项一项地改变样式,而是使用 CSS class 一次性改变样式
  4. 使用documentFragment操作 DOM
  5. 动画使用absolute定位或fixed定位,这样可以减少对其他元素的影响
  6. 只在必要时才显示隐藏元素
  7. 使用虚拟DOM(virtual DOM)库
// 引发两次回流
box.style.top = '100px';
console.log(box.style.top);//=>'100px'
box.style.left = '100px';

// 引发一次回流
box.style.top = '100px';
box.style.left = '100px';
console.log(box.style.top);//=>'100px'

JavaScript_定时器之setTimeout

JavaScript 提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()setInterval()这两个函数来完成。它们向任务队列添加定时任务

setTimeout函数用来指定某个函数或某段代码,在多少毫秒之后执行。它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器。

var timerId = setTimeout(func|code, delay);

setTimeout函数接受两个参数,第一个参数func|code是将要推迟执行的函数名或者一段代码,第二个参数delay是推迟执行的毫秒数

setTimeout(function(){
    console.log("定时器")
},1000)

温馨提示

还有一个需要注意的地方,如果回调函数是对象的方法,那么setTimeout使得方法内部的this关键字指向全局环境,而不是定义时所在的那个对象

var name = "sxt";
var user = {
    name: "itbaizhan",
    getName: function () {
        setTimeout(function(){
            console.log(this.name);
        },1000)
    }
};
user.getName();

解决方案

var name = "sxt";
var user = {
    name: "itbaizhan",
    getName: function () {
        var that = this;
        setTimeout(function(){
            console.log(that.name);
        },1000)
    }
};
user.getName();

定时器可以进行取消

var id = setTimeout(f, 1000);
clearTimeout(id);
    <script>

        // var timer = setTimeout(function(){
        //     console.log("hello");
        // },5000)

        // // this在不被改变的情况下,在定时器中指向window

        // var username = "sxt";
        // var user = {
        //     username:"itbaizhan",
        //     getName:function(){
        //         setTimeout(function(){
        //             // this指向window
        //             console.log(this.username);
        //         },1000)
        //     }
        // }

        // user.getName(); // sxt


        // function logHello(){
        //     console.log("hello");
        // }
        // var timer = setTimeout(logHello,3000)


        // var username = "sxt";
        // var user = {
        //     username: "itbaizhan",
        //     getName: function () {
        //         var that = this;
        //         setTimeout(function () {
        //             // this指向window
        //             console.log(that.username);
        //         }, 1000)
        //     }
        // }

        // user.getName(); // itbaizhan


        // var timer = setTimeout(function(){
        //     console.log("hello");
        // },3000)

        // clearTimeout(timer);

    </script>

JavaScript_定时器之setInterval

setInterval函数的用法与setTimeout完全一致,区别仅仅在于setInterval指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行

var timer = setInterval(function() {
  console.log(2);
}, 1000)

通过setInterval方法实现网页动画

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #box {
            width: 100px;
            height: 100px;
            background: red;
        }
    </style>
</head>

<body>

    <div id="box"></div>

    <script>

        setInterval(function () {
            console.log("hello");
        }, 1000)

    </script>

    <script>

        var box = document.getElementById('box');
        var opacity = 1;
        var timer = setInterval(function () {
            opacity -= 0.05;
            if (opacity <= 0) {
                // 清除定时器 
                clearInterval(timer)
            } else {
                box.style.opacity = opacity
            }
        }, 30)


        
        setInterval(function () {
            console.log(new Date().toLocaleTimeString());
        }, 1000)


    </script>

</body>

</html>

定时器实操 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        body {
            background-color: gray;
        }
        .container {
            width: 300px;
            height: 200px;
            background-color: #fff;
            margin: 100px auto;
        }
        .container .up {
            height: 50px;
            width: 100%;
        }
        .container .up ul {
            list-style-type: none;
            text-align: center;
        }
        .container .up ul li {
            float: left;
            width: 60px;
            height: 50px;
            line-height: 50px;
        }
        .container .up ul li a {
            text-decoration: none;
            font-size: 20px;
        }
        .select {
            border-bottom: 2px solid orange;
        }
        .container .down {
            height: 100px;
            width: 100%;
            position: relative;
            text-align: center;
        }
        .container .down div {
            position: absolute;
            line-height: 100px;
            height: 100%;
            width: 100%;
            display: none;
        }
        .container .down div.div-select {
            display: block;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="up">
            <ul>
                <li class="select"><a href="#">百度</a></li>
                <li><a href="#">新浪</a></li>
                <li><a href="#">淘宝</a></li>
                <li><a href="#">京东</a></li>
                <li><a href="#">网易</a></li>
            </ul>
        </div>
        <div class="down">
            <div class="div-select">百度内容</div>
            <div>新浪内容</div>
            <div>淘宝内容</div>
            <div>京东内容</div>
            <div>网易内容</div>
        </div>
    </div>
    <script>
        // 1. 获取到页面所有的元素
        var lis = document.querySelector(".up").querySelectorAll("li");
        var divs = document.querySelector(".down").querySelectorAll("div");
        var timer = null;
        var delay = 300;
        // 闭包帮我们保存变量到内存中
        for (var i = 0; i < lis.length; i++) {
            (function (i) {
                lis[i].onmouseenter = function () {
                    timer = setTimeout(function () {
                        for (var j = 0; j < lis.length; j++) {
                            lis[j].removeAttribute("class");
                            divs[j].removeAttribute("class")
                        }
                        lis[i].setAttribute("class", "select")
                        divs[i].setAttribute("class", "div-select")
                    }, delay)
                }
            }(i))
            lis[i].onmouseleave = function () {
                clearTimeout(timer)
            }
        }
/**
                 * 1. 获取元素
                 * 2. 闭包
                 * 3. 事件:鼠标滑动事件
                 * 4. 属性的操作:添加、删除
                 */
    </script>
</body>
</html>

JavaScript_防抖(debounce)

防抖严格算起来应该属于性能优化的知识,但实际上遇到的频率相当高,处理不当或者放任不管就容易引起浏览器卡死。

从滚动条监听的例子说起

先说一个常见的功能,很多网站会提供这么一个按钮:用于返回顶部。

这个按钮只会在滚动到距离顶部一定位置之后才出现,那么我们现在抽象出这个功能需求-- 监听浏览器滚动事件,返回当前滚条与顶部的距离这个需求很简单,直接写

function showTop  () {
    var scrollTop = document.documentElement.scrollTop;
    console.log('滚动条位置:' + scrollTop);
}
window.onscroll  = showTop

在运行的时候会发现存在一个问题:这个函数的默认执行频率,太!高!了!。 高到什么程度呢?以chrome为例,我们可以点击选中一个页面的滚动条,然后点击一次键盘的【向下方向键】,会发现函数执行了8-9次!

然而实际上我们并不需要如此高频的反馈,毕竟浏览器的性能是有限的,不应该浪费在这里,所以接着讨论如何优化这种场景。

基于上述场景,首先提出第一种思路:在第一次触发事件时,不立即执行函数,而是给出一个期限值比如200ms,然后

  1. 如果在200ms内没有再次触发滚动事件,那么就执行函数
  2. 如果在200ms内再次触发滚动事件,那么当前的计时取消,重新开始计时

效果:如果短时间内大量触发同一事件,只会执行一次函数

实现:既然前面都提到了计时,那实现的关键就在于setTimeout这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现

function debounce(fn,delay){
    let timer = null //借助闭包
    return function() {
        if(timer){
            clearTimeout(timer) 
        }
        timer = setTimeout(fn,delay) // 简化写法
    }
}
// 然后是旧代码
function showTop  () {
    var scrollTop = document.documentElement.scrollTop;
    console.log('滚动条位置:' + scrollTop);
}
window.onscroll = debounce(showTop,300)

到这里,已经把防抖实现了

防抖定义

对于短时间内连续触发的事件(上面的滚动事件),防抖的含义就是让某个时间期限(如上面的1000毫秒)内,事件处理函数只执行一次

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box {
            height: 300px;
        }
    </style>
</head>

<body>

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

    <script>

        // var timer = null;
        // function debounce() {
        //     if (timer) {
        //         clearTimeout(timer)
        //     }
        //     timer = setTimeout(function () {
        //         var scollTop = document.documentElement.scrollTop;
        //         console.log(scollTop);
        //     },300)
        // }

        // window.onscroll = function () {
        //     debounce();
        // }

        /**
         * 1. 定时器
         * 2. 闭包
         * 3. 事件机制
         *     事件在注册的时候,只执行一次,后续的不间断的触发事件,是在执行事件里面的内容
         *     不是在一直触发事件函数
         */


        function debounce(fn, delay) {
            console.log(111);
            var timer = null; // 局部作用域,不污染全局命名空间
            return function () {
                if (timer) {
                    clearTimeout(timer)
                }
                timer = setTimeout(fn, delay)
            }
        }

        function backTop() {
            var scollTop = document.documentElement.scrollTop;
            console.log(scollTop);
        }

        window.onscroll = debounce(backTop, 300)
        window.onscroll = debounce//会打印111

        // window.onscroll = function () {
        //     var result = debounce(backTop, 300);
        //     result();
        // }
        
        // window.onscroll = function () {
        //     var result = debounce(backTop, 300)();
        //    
        // }

        // // 只有第一次注册的时候执行一次,不间断执行的是里面的函数体
        // div.onclick = function(){
        //     console.log("111");
        // }

    </script>

</body>

</html>

JavaScript_节流(throttle)

节流严格算起来应该属于性能优化的知识,但实际上遇到的频率相当高,处理不当或者放任不管就容易引起浏览器卡死

继续思考,使用上面的防抖方案来处理问题的结果是

如果在限定时间段内,不断触发滚动事件(比如某个用户闲着无聊,按住滚动不断的拖来拖去),只要不停止触发,理论上就永远不会输出当前距离顶部的距离

但是如果产品同学的期望处理方案是:即使用户不断拖动滚动条,也能在某个时间间隔之后给出反馈呢?

其实很简单:我们可以设计一种类似控制阀门一样定期开放的函数,也就是让函数执行一次后,在某个时间段内暂时失效,过了这段时间后再重新激活(类似于技能冷却时间)

效果:如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效

实现

这里借助setTimeout来做一个简单的实现,加上一个状态位valid来表示当前函数是否处于工作状态

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box {
            height: 300px;
        }
    </style>
</head>

<body>

    <div class="box">内哦给你</div>
    <div class="box">内哦给你</div>
    <div class="box">内哦给你</div>
    <div class="box">内哦给你</div>
    <div class="box">内哦给你</div>
    <div class="box">内哦给你</div>


    <script>

        function throttle(fn, delay) {
            var valid = true;

            return function () {
                if(!valid){
                    // 暂不接客
                    return false; // 后面的代码不在执行
                }
                valid = false;
                setTimeout(function () {
                    fn();
                    valid = true;
                },delay)
            }
        }

        function backTop() {
            var scollHeight = document.documentElement.scrollTop;
            console.log(scollHeight);
        }

        window.onscroll = throttle(backTop,1000);


    </script>

</body>

</html>

如果一直拖着滚动条进行滚动,那么会以1000ms的时间间隔,持续输出当前位置和顶部的距离

讲完了这两个技巧,下面介绍一下平时开发中常遇到的场景:

  1. 搜索框input事件,例如要支持输入实时搜索可以使用节流方案(间隔一段时间就必须查询相关内容),或者实现输入间隔大于某个值(如500ms),就当做用户输入完成,然后开始搜索,具体使用哪种方案要看业务需求
  2. 页面resize事件,常见于需要做页面适配的时候。需要根据最终呈现的页面情况进行dom渲染(这种情形一般是使用防抖,因为只需要判断最后一次的变化情况)

 JavaScript_window对象_属性

浏览器里面,window对象(注意,w为小写)指当前的浏览器窗口。它也是当前页面的顶层对象,即最高一层的对象,所有其他对象都是它的下属

a = 1;
window.a // 1

window.screenX,window.screenY

window.screenXwindow.screenY属性,返回浏览器窗口左上角相对于当前屏幕左上角的水平距离和垂直距离(单位像素)。这两个属性只读

console.log(window.screenX);
console.log(window.screenY);

window.innerHeight,window.innerWidth

window.innerHeightwindow.innerWidth属性,返回网页在当前窗口中可见部分的高度和宽度,即“视口”(viewport)的大小(单位像素)。这两个属性只读

console.log(window.innerHeight);
console.log(window.innerWidth);

温馨提示

这两个属性值包括滚动条的高度和宽度

 window.outerHeight,window.outerWidth

window.outerHeightwindow.outerWidth属性返回浏览器窗口的高度和宽度,包括浏览器菜单和边框(单位像素)。这两个属性只读

console.log(window.outerHeight);
console.log(window.outerWidth);

window.scrollX,window.scrollY

window.scrollX属性返回页面的水平滚动距离,window.scrollY属性返回页面的垂直滚动距离,单位都为像素。这两个属性只读

console.log(window.scrollX);
console.log(window.scrollY);

window.pageXOffset,window.pageYOffset

window.pageXOffset属性和window.pageYOffset属性,是window.scrollXwindow.scrollY别名

JavaScript_window对象_方法

window.alert(),window.prompt(),window.confirm()

window.alert()window.prompt()window.confirm()都是浏览器与用户互动的全局方法。它们会弹出不同的对话框,要求用户做出回应。注意,这三个方法弹出的对话框,都是浏览器统一规定的式样,无法定制

window.alert()

window.alert()方法弹出的对话框,只有一个“确定”按钮,往往用来通知用户某些信息

window.alert('Hello World');

window.prompt()

window.prompt()方法弹出的对话框,提示文字的下方,还有一个输入框,要求用户输入信息,并有“确定”和“取消”两个按钮。它往往用来获取用户输入的数据

var result = prompt('您的年龄?', 25)
console.log(result);

window.confirm()

window.confirm()方法弹出的对话框,除了提示信息之外,只有“确定”和“取消”两个按钮,往往用来征询用户是否同意

confirm方法返回一个布尔值,如果用户点击“确定”,返回true;如果用户点击“取消”,则返回false

var result = confirm('你最近好吗?');

var okay = confirm('Please confirm this message.');
if (okay) {
  // 用户按下“确定”
} else {
  // 用户按下“取消”
}

window.open()

window.open方法用于新建另一个浏览器窗口,类似于浏览器菜单的新建窗口选项。它会返回新窗口的引用,如果无法新建窗口,则返回null

window.open("https://itbaizhan.com")

JavaScript_Navigator对象

window.navigator属性指向一个包含浏览器和系统信息的 Navigator 对象。脚本通过这个属性了解用户的环境信息

navigator.userAgent属性返回浏览器的 User Agent 字符串,表示用户设备信息,包含了浏览器的厂商、版本、操作系统等信息

userAgent可以大致准确地识别手机浏览器,方法就是测试是否包含mobi字符串

var ua = navigator.userAgent.toLowerCase();

if (ua.indexOf("mobi") > -1) {
  // 手机浏览器
} else {
  // 非手机浏览器
}

Navigator.plugins属性返回一个类似数组的对象,成员是 Plugin 实例对象,表示浏览器安装的插件,比如 Flash、ActiveX 等

var pluginsLength = navigator.plugins.length;

for (var i = 0; i < pluginsLength; i++) {
  console.log(navigator.plugins[i].name);
  console.log(navigator.plugins[i].filename);
  console.log(navigator.plugins[i].description);
  console.log(navigator.plugins[i].version);
}

Navigator.platform属性返回用户的操作系统信息,比如MacIntelWin32Linux x86_64

navigator.platform
// 'Win32'

Navigator.language属性返回一个字符串,表示浏览器的首选语言。该属性只读

navigator.language
// 'zh-CN'

Navigator.languages属性返回一个数组,表示用户可以接受的语言

navigator.languages  
// ['zh-CN', 'zh']

JavaScript_Screen对象

Screen 对象表示当前窗口所在的屏幕,提供显示设备的信息。window.screen属性指向这个对象

Screen.height

浏览器窗口所在的屏幕的高度(单位像素)。除非调整显示器的分辨率,否则这个值可以看作常量,不会发生变化。显示器的分辨率与浏览器设置无关,缩放网页并不会改变分辨率

Screen.width

浏览器窗口所在的屏幕的宽度(单位像素)

console.log(screen.width);

Screen.availHeight

浏览器窗口可用的屏幕高度(单位像素)。因为部分空间可能不可用,比如系统的任务栏或者 Mac 系统屏幕底部的 Dock 区,这个属性等于height减去那些被系统组件的高度

screen.availHeight

Screen.availWidth

浏览器窗口可用的屏幕宽度(单位像素)

screen.availWidth

Screen.pixelDepth

整数,表示屏幕的色彩位数,比如24表示屏幕提供24位色彩

screen.pixelDepth
// 24

Screen.orientation

返回一个对象,表示屏幕的方向。该对象的type属性是一个字符串,表示屏幕的具体方向,landscape-primary表示横放,landscape-secondary表示颠倒的横放,portrait-primary表示竖放,portrait-secondary表示颠倒的竖放。

screen.orientation
// {angle: 270, type: 'portrait-primary', onchange: null}

JavaScript_History对象

window.history属性指向 History 对象,它表示当前窗口的浏览历史

History 对象保存了当前窗口访问过的所有页面网址

window.history.length

History.back()

History.back():移动到上一个网址,等同于点击浏览器的后退键。对于第一个访问的网址,该方法无效果

history.back();

History.forward()

History.forward():移动到下一个网址,等同于点击浏览器的前进键。对于最后一个访问的网址,该方法无效果

history.forward();

History.go()

History.go():接受一个整数作为参数,以当前网址为基准,移动到参数指定的网址,比如go(1)相当于forward()go(-1)相当于back()。如果参数超过实际存在的网址范围,该方法无效果;如果不指定参数,默认参数为0,相当于刷新当前页面

history.go(-2);

温馨提示

移动到以前访问过的页面时,页面通常是从浏览器缓存之中加载,而不是重新要求服务器发送新的网页。

 JavaScript_Cookie对象

Cookie 是服务器保存在浏览器的一小段文本信息,每个 Cookie 的大小一般不能超过4KB。浏览器每次向服务器发出请求,就会自动附上这段信息

Cookie 的目的就是区分用户,以及放置状态信息,它的使用场景主要如下

  1. 对话(session)管理:保存登录状态、购物车等需要记录的信息

  2. 个性化信息:保存用户的偏好,比如网页的字体大小、背景色等等

  3. 追踪用户:记录和分析用户行为

Cookie 不是一种理想的客户端存储机制。它的容量很小(4KB),缺乏数据操作接口,而且会影响性能。客户端存储建议使用 Web storage API 。只有那些每次请求都需要让服务器知道的信息,才应该放在 Cookie 里面

每个 Cookie 都有以下几方面的元数据

  • Cookie 的名字
  • Cookie 的值(真正的数据写在这里面)
  • 到期时间(超过这个时间会失效)
  • 所属域名(默认为当前域名)
  • 生效的路径(默认为当前网址)

不同浏览器对 Cookie 数量和大小的限制,是不一样的。一般来说,单个域名设置的 Cookie 不应超过30个,每个 Cookie 的大小不能超过 4KB。超过限制以后,Cookie 将被忽略,不会被设置

读取cookie

document.cookie

 JavaScript_Cookie属性

Expires

Expires属性指定一个具体的到期时间,到了指定时间以后,浏览器就不再保留这个 Cookie。它的值是 UTC 格式,可以使用Date.prototype.toUTCString()进行格式转换

如果不设置该属性,或者设为null,Cookie 只在当前会话(session)有效,浏览器窗口一旦关闭,当前 Session 结束,该 Cookie 就会被删除。另外,浏览器根据本地时间,决定 Cookie 是否过期,由于本地时间是不精确的,所以没有办法保证 Cookie 一定会在服务器指定的时间过期。

document.cookie = "name=iwen;Expires=Fri, 31 Dec 2021 16:00:00 GMT"

Max-Age

Max-Age属性指定从现在开始 Cookie 存在的秒数,比如60 * 60 * 24 * 365(即一年)。过了这个时间以后,浏览器就不再保留这个 Cookie

如果同时指定了ExpiresMax-Age,那么Max-Age的值将优先生效

document.cookie = "name=iwen;Max-Age=3600"

Domain

Domain属性指定 Cookie 属于哪个域名,以后浏览器向服务器发送 HTTP 请求时,通过这个属性判断是否要附带某个 Cookie

Path

Path属性指定浏览器发出 HTTP 请求时,哪些路径要附带这个 Cookie。只要浏览器发现,Path属性是 HTTP 请求路径的开头一部分,就会在头信息里面带上这个 Cookie。比如,Path属性是/,那么请求/docs路径也会包含该 Cookie。当然,前提是 Domain 属性必须符合条件

Secure

Secure属性指定浏览器只有在加密协议 HTTPS 下,才能将这个 Cookie 发送到服务器。另一方面,如果当前协议是 HTTP,浏览器会自动忽略服务器发来的Secure属性。该属性只是一个开关,不需要指定值。如果通信是 HTTPS 协议,该开关自动打开

HttpOnly

HttpOnly属性指定该 Cookie 无法通过 JavaScript 脚本拿到,主要是document.cookie属性、XMLHttpRequest对象和 Request API 都拿不到该属性。这样就防止了该 Cookie 被脚本读到,只有浏览器发出 HTTP 请求时,才会带上该 Cookie

JavaScript_封装Cookie(在服务器运行)


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <h3>学习Cookie</h3>

    <script>


        /*
            1. 设置
            2. 获取
            3. 删除
        */

        var cookie = {
            // name  value  过期时间
            set:function(name,value,days){
                var d = new Date();
                d.setDate(d.getDate() + days); // 设置过期时间  name=itbaizhan;
                document.cookie = name + "=" + value +";expires=" + d+";";
            },
            // 读取cookie,知道你要读取的是那个cookie
            get:function(name){
                var cookiesArr = document.cookie.split("; ")
                for(var i = 0;i< cookiesArr.length;i++){
                    var newArr = cookiesArr[i].split("=");
                    if(name === newArr[0]){
                        return newArr[1]
                    }
                }
            },
            // 干掉哪一个cookie
            unset:function(name){
                this.set(name,"",-1)
            }
        }

        // cookie.set("sxt","iwen",30);
        // console.log(cookie.get("name"));;
        cookie.unset("name");


    </script>
    
</body>
</html>

JavaScript_call_apply_bind函数

无论是apply、call还是bind其实都是改变this的指向,我们先来看一个例子

var obj = {
    name:"小张",
    getName:function(){
        console.log(this.name)
    }
}
obj.getName(); // 小张

下面我们来看一下通过他们来改变this指向

var obj = {
    name:"小张",
    getName:function(){
        console.log(this.name)
    }
}
var newObj = {
    name:'小王'
}
obj.getName.call(newObj); // 小王
obj.getName.apply(newObj); // 小王
obj.getName.bind(newObj)(); // 小王

由此得出结论,bind 返回的是一个新的函数,你必须调用它才会被执行

我们再来看一下apply和call的区别

var obj = {
    name:"小张",
    getName:function(city){
        console.log(this.name,city)
    }
}
var newObj = {
    name:'小王'
}
obj.getName.call(newObj,'北京'); 
obj.getName.apply(newObj,['上海']);
obj.getName.bind(newObj,'深圳')(); 

第一个参数:this的指向,第二个参数为方法传递参数

常见应用场景

var arr = [10,20,30]
Math.max.apply(null,arr) // 30

var arr = [10,20,30]
Math.max.call(null,...arr)

null代表指向window对象,这里是因为Array本身是window对象的子元素

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

    <script>

        /*
            回顾this指向
                1. 事件中的this,指向当前DOM元素
                2. 对象中的this,指向当前调用者
                3. 闭包中的this,指向window
                4. 定时器中的this,指向window
                5. call、apply和bind改变this指向
        */

        // var user = {
        //     name:"itbaizhan",
        //     getName:function(){
        //         console.log(this.name);
        //     }
        // }


        // var username = "sxt"
        // function getFn(){
        //     var username = "itbaizhan"
        //     return function(){
        //         console.log(this.username);
        //     }
        // }

        // var name = "sxt"
        // var user = {
        //     name:"itbaizhan",
        //     getName:function(){
        //         setTimeout(function(){
        //             console.log(this.name);
        //         })
        //     }
        // }

        // user.getName()
    </script>

    <script>

        var user = {
            name: "itbaizhan",
            getName: function (city) {
                console.log(this.name,city);
            }
        }

        var people = {
            name: "sxt"
        }

        // user.getName(); // 指向user
        // this指向,传递的额外参数
        // user.getName.call(people); // sxt
        // user.getName.apply(people); // sxt
        // user.getName.bind(people)(); // sxt
        // 由此得出结论,bind 返回的是一个新的函数,你必须调用它才会被执行

        // call和apply的区别
        // call和apply接受的参数是不同的
        // user.getName.call(people,"北京"); // sxt 北京
        // user.getName.apply(people, ["北京"]); // sxt 北京


        var arr = [10,20,30];
        console.log(Math.max.apply(window,arr)); // null === window

        console.log(Math.max.call(window,10,20,30));
        console.log(Math.max(10,20,30));


    </script>

</body>

</html>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值