Rumah > hujung hadapan web > tutorial js > [Kemahiran Lanjutan] Sembilan soalan temuduga hadapan untuk membantu anda menyatukan pengetahuan anda!

[Kemahiran Lanjutan] Sembilan soalan temuduga hadapan untuk membantu anda menyatukan pengetahuan anda!

青灯夜游
Lepaskan: 2022-10-18 20:33:15
ke hadapan
1771 orang telah melayarinya

Artikel ini berkongsi kemahiran bahagian hadapan lanjutan, menyusun dan meringkaskan sembilan soalan temu duga bahagian hadapan, dan membantu anda menyatukan mata pengetahuan saya harap ia akan membantu semua orang.

[Kemahiran Lanjutan] Sembilan soalan temuduga hadapan untuk membantu anda menyatukan pengetahuan anda!

Soalan pertama: Pengesanan jenis keselamatan - perbezaan dan kecacatan antara jenis dan contoh, serta penyelesaian

Kedua-dua kaedah ini boleh digunakan untuk menentukan jenis pembolehubah

Perbezaan: Yang pertama adalah untuk menentukan jenis pembolehubah itu, yang terakhir adalah untuk menentukan sama ada pembolehubah itu daripada jenis tertentu, dan pulangan nilai ialah nilai Boolean

(1) jenis

Kecacatan:

1 Jenis data khusus pembolehubah tidak boleh ditentukan seperti tatasusunan , biasa, tarikh dan objek, kerana ia semua akan mengembalikan objek, Walau bagaimanapun, fungsi boleh dinilai Jika objek pengesanan adalah ungkapan biasa, "fungsi" akan dikembalikan dengan salah apabila menggunakan typeof dalam Safari dan Chrome, dan pelayar lain akan. kembalikan objek.

2. Penghakiman Apabila null dikembalikan, objek dikembalikan Ini adalah kecacatan js Apabila NaN dinilai, nilai pulangan adalah nombor

(2) instanceof can. digunakan untuk mengesan sama ada pembolehubah itu daripada jenis tertentu dan mengembalikan nilai Boolean , dan boleh menentukan sama ada pembolehubah ini adalah contoh bagi fungsi tertentu 🎜> jelas sekali kedua-duanya num, dan kedua-duanya adalah 1, hanya kerana yang pertama bukan objek, ia adalah jenis asas, jadi ia kembali palsu secara langsung, dan yang kedua dikapsulkan ke dalam objek, jadi ia benar.

let num = 1
num instanceof Number // false


num = new Number(1)
num instanceof Number // true
Salin selepas log masuk
Perhatian yang ketat harus diberikan kepada isu ini di sini Ada yang mengatakan bahawa jika __proto__ sasaran pengesanan adalah sama dengan prototaip pembina, ia akan kembali benar objek, seperti:

Selain itu, instanceof mempunyai kelemahan lain: jika terdapat berbilang bingkai pada halaman, iaitu berbilang persekitaran global, maka saya mentakrifkan Array dalam bingkai a, dan kemudian gunakan instanceof dalam bingkai b. Untuk menilai, maka adalah mustahil untuk mencari tatasusunan dalam bingkai b pada rantaian prototaip tatasusunan, dan ia akan dinilai bahawa tatasusunan itu bukan tatasusunan.

let num = 1
num.__proto__ === Number.prototype // true
num instanceof Number // false

num = new Number(1)
num.proto === Number.prototype // true
num instanceof Number // true

num.proto === (new Number(1)).proto // true
Salin selepas log masuk

Penyelesaian

: Gunakan kaedah Object.prototype.toString.call(value) untuk memanggil objek dan dapatkan nama pembina objek. Ia boleh menyelesaikan masalah rangka kerja silang instanceof. Kelemahannya ialah untuk jenis yang ditentukan pengguna, ia hanya akan mengembalikan [objek Objek]

Soalan kedua: Memandangkan instanceof disebut, bagaimana pula dengan melaksanakan instanceof. dengan tangan?

Soalan ketiga: Pembina selamat skop - apabila kita mencipta pembina baharu, kita boleh mendapatkan contoh Bagaimana jika kita terlupa menulis baharu?
// [1,2,3] instanceof Array ---- true

// L instanceof R
// 变量R的原型 存在于 变量L的原型链上
function instance_of(L,R){    
    // 验证如果为基本数据类型,就直接返回false
    const baseType = ['string', 'number','boolean','undefined','symbol']
    if(baseType.includes(typeof(L))) { return false }
    
    let RP  = R.prototype;  //取 R 的显示原型
    L = L.__proto__;       //取 L 的隐式原型
    while(true){           // 无线循环的写法(也可以使 for(;;) )
        if(L === null){    //找到最顶层
            return false;
        }
        if(L === RP){       //严格相等
            return true;
        }
        L = L.__proto__;  //没找到继续向上一层原型链查找
    }
}
Salin selepas log masuk

Contohnya

Apa yang akan berlaku dengan ini? , bagaimana untuk menyelesaikan masalah? Jika

function Person(){
    this.name = "小红"
}


p = Person();
Salin selepas log masuk
digunakan secara langsung, ini akan dipetakan ke tetingkap objek global. Penyelesaiannya boleh: mula-mula sahkan bahawa objek ini adalah contoh jenis yang betul. Jika tidak, tika baharu dibuat dan dikembalikan. Sila lihat contoh di bawah

Soalan keempat: Mari kita bincangkan tentang fungsi pemuatan malas
function Person(){
    if(this instanceof Person){
        this.name = "小红"
    }else{
        return  new Person()
    }
}


p = Person();
Salin selepas log masuk

Dalam kod JavaScript, disebabkan oleh perbezaan tingkah laku antara penyemak imbas, Kebanyakan kod JavaScript mengandungi sejumlah besar pernyataan if untuk menyemak ciri penyemak imbas dan menyelesaikan isu keserasian dengan penyemak imbas yang berbeza. Contohnya, fungsi untuk menambah acara:

Setiap kali anda memanggil addEvent(), anda mesti menyemak dengan teliti keupayaan yang disokong oleh penyemak imbas. Mula-mula semak sama ada kaedah addEventListener disokong Jika tidak, kemudian semak sama ada kaedah attachEvent disokong Jika ia belum disokong lagi, gunakan kaedah DOM tahap 0 untuk menambah acara. Semasa panggilan ke addEvent(), proses ini mesti diselesaikan setiap kali. Malah, jika penyemak imbas menyokong salah satu kaedah, ia akan sentiasa menyokongnya, dan tidak perlu mengesan cawangan lain Dalam erti kata lain, pernyataan if tidak perlu dilaksanakan setiap kali, dan kod itu boleh berjalan lebih cepat . Penyelesaiannya dipanggil pemuatan malas. Pemuatan malas yang dipanggil bermaksud bahawa cawangan if bagi fungsi hanya akan dilaksanakan sekali, dan apabila fungsi dipanggil kemudian, kod cawangan yang disokong akan dimasukkan terus. Terdapat dua cara untuk melaksanakan pemuatan malas Yang pertama ialah apabila fungsi dipanggil buat kali pertama, fungsi itu sendiri diproses dua kali Fungsi akan ditimpa sebagai fungsi yang memenuhi syarat cawangan, supaya panggilan ke fungsi asal tidak perlu Selepas melepasi cawangan pelaksanaan, kita boleh menulis semula addEvent() menggunakan pemuatan malas dengan cara berikut.

function addEvent (element, type, handler) {
    if (element.addEventListener) {
        element.addEventListener(type, handler, false);
    } else if (element.attachEvent) {
        element.attachEvent("on" + type, handler);
    } else {
        element["on" + type] = handler;
    }
}
Salin selepas log masuk

Dalam addEvent() yang dimuatkan malas ini, setiap cabang pernyataan if memberikan nilai kepada pembolehubah addEvent, merangkumi fungsi asal dengan berkesan. Langkah terakhir ialah memanggil fungsi tugasan baharu. Pada kali seterusnya addEvent() dipanggil, fungsi yang baru ditetapkan akan dipanggil terus, jadi tidak perlu melaksanakan pernyataan if.

function addEvent (type, element, handler) {
    if (element.addEventListener) {
        addEvent = function (type, element, handler) {
            element.addEventListener(type, handler, false);
        }
    }
    else if(element.attachEvent){
        addEvent = function (type, element, handler) {
            element.attachEvent('on' + type, handler);
        }
    }
    else{
        addEvent = function (type, element, handler) {
            element['on' + type] = handler;
        }
    }
    return addEvent(type, element, handler);
}
Salin selepas log masuk
Cara kedua untuk melaksanakan pemuatan malas ialah dengan menentukan fungsi yang sesuai apabila mengisytiharkan fungsi tersebut. Dengan cara ini, tiada kehilangan prestasi apabila fungsi dipanggil buat kali pertama, tetapi hanya kehilangan prestasi kecil apabila kod dimuatkan. Berikut ialah addEvent() ditulis semula mengikut idea ini.

Teknik yang digunakan dalam contoh ini adalah untuk mencipta fungsi laksana sendiri tanpa nama dan melalui cawangan yang berbeza untuk menentukan fungsi mana yang harus digunakan untuk pelaksanaan Logik sebenar adalah sama, perbezaannya adalah penggunaan ungkapan fungsi (menggunakan var untuk mentakrifkan fungsi) dan fungsi tanpa nama baharu Selain itu, setiap cawangan mengembalikan fungsi yang betul dan segera memberikannya kepada addEvent pembolehubah.

惰性载入函数的优点只执行一次if分支,避免了函数每次执行时候都要执行if分支和不必要的代码,因此提升了代码性能,至于那种方式更合适,就要看您的需求而定了。

第五问:谈一下函数节流

概念:限制一个函数在一定时间内只能执行一次。

主要实现思路 就是通过 setTimeout 定时器,通过设置延时时间,在第一次调用时,创建定时器,先设定一个变量true,写入需要执行的函数。第二次执行这个函数时,会判断变量是否true,是则返回。当第一次的定时器执行完函数最后会设定变量为false。那么下次判断变量时则为false,函数会依次运行。目的在于在一定的时间内,保证多次函数的请求只执行最后一次调用。

函数节流的代码实现

function throttle(fn,wait){
    var timer = null;
    return function(){
        var context = this;
        var args = arguments;
        if(!timer){
            timer = setTimeout(function(){
                fn.apply(context,args);
                timer = null;
            },wait)
        }
    }
}


function handle(){
console.log(Math.random());
}

window.addEventListener("mousemove",throttle(handle,1000));
Salin selepas log masuk

函数节流的应用场景(throttle)

  • DOM 元素的拖拽功能实现(mousemove)
  • 高频点击提交,表单重复提交
  • 搜索联想(keyup)
  • 计算鼠标移动的距离(mousemove)
  • 监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断
  • 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
  • 监听滚动事件判断是否到页面底部自动加载更多:给 scroll 加了 debounce 后,只有用户停止滚动后,- - 才会判断是否到了页面底部;如果是 throttle 的话,只要页面滚动就会间隔一段时间判断一次.

第六问:谈一下函数防抖

概念:函数防抖(debounce),就是指触发事件后,在 n 秒内函数只能执行一次,如果触发事件后在 n 秒内又触发了事件,则会重新计算函数延执行时间。

函数防抖的要点,是需要一个 setTimeout 来辅助实现,延迟运行需要执行的代码。如果方法多次触发,则把上次记录的延迟执行代码用 clearTimeout 清掉,重新开始计时。若计时期间事件没有被重新触发,等延迟时间计时完毕,则执行目标代码。

函数防抖的代码实现

function debounce(fn,wait){
    var timer = null;
    return function(){
        if(timer !== null){
            clearTimeout(timer);
        }
        timer = setTimeout(fn,wait);
    }
}
    
function handle(){
    console.log(Math.random());
}
    
window.addEventListener("resize",debounce(handle,1000));
Salin selepas log masuk

函数防抖的使用场景 函数防抖一般用在什么情况之下呢?一般用在,连续的事件只需触发一次回调的场合。具体有:

  • 搜索框搜索输入。只需用户最后一次输入完,再发送请求;
  • 用户名、手机号、邮箱输入验证;
  • 浏览器窗口大小改变后,只需窗口调整完后,再执行 resize 事件中的代码,防止重复渲染。

目前遇到过的用处就是这些,理解了原理与实现思路,小伙伴可以把它运用在任何需要的场合,提高代码质量。

第七问:谈一下requestAnimationFrame

动画原理 : 眼前所看到图像正在以每秒60次的频率刷新,由于刷新频率很高,因此你感觉不到它在刷新。而动画本质就是要让人眼看到图像被刷新而引起变化的视觉效果,这个变化要以连贯的、平滑的方式进行过渡。 那怎么样才能做到这种效果呢?

刷新频率为60Hz的屏幕每16.7ms刷新一次,我们在屏幕每次刷新前,将图像的位置向左移动一个像素,即1px。这样一来,屏幕每次刷出来的图像位置都比前一个要差1px,因此你会看到图像在移动;由于我们人眼的视觉停留效应,当前位置的图像停留在大脑的印象还没消失,紧接着图像又被移到了下一个位置,因此你才会看到图像在流畅的移动,这就是视觉效果上形成的动画。

与setTimeout相比较

理解了上面的概念以后,我们不难发现,setTimeout 其实就是通过设置一个间隔时间来不断的改变图像的位置,从而达到动画效果的。但我们会发现,利用seTimeout实现的动画在某些低端机上会出现卡顿、抖动的现象。 这种现象的产生有两个原因:

  • setTimeout的执行时间并不是确定的。在Javascript中, setTimeout 任务被放进了异步队列中,只有当主线程上的任务执行完以后,才会去检查该队列里的任务是否需要开始执行,因此 setTimeout 的实际执行时间一般要比其设定的时间晚一些。

  • 刷新频率受屏幕分辨率和屏幕尺寸的影响,因此不同设备的屏幕刷新频率可能会不同,而 setTimeout只能设置一个固定的时间间隔,这个时间不一定和屏幕的刷新时间相同。

以上两种情况都会导致setTimeout的执行步调和屏幕的刷新步调不一致,从而引起丢帧现象

requestAnimationFrame:与setTimeout相比,requestAnimationFrame最大的优势是由系统来决定回调函数的执行时机。具体一点讲,如果屏幕刷新率是60Hz,那么回调函数就每16.7ms被执行一次,如果刷新率是75Hz,那么这个时间间隔就变成了1000/75=13.3ms,换句话说就是,requestAnimationFrame的步伐跟着系统的刷新步伐走。它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致动画出现卡顿的问题。

除此之外,requestAnimationFrame还有以下两个优势:

  • CPU节能:使用setTimeout实现的动画,当页面被隐藏或最小化时,setTimeout 仍然在后台执行动画任务,由于此时页面处于不可见或不可用状态,刷新动画是没有意义的,完全是浪费CPU资源。而requestAnimationFrame则完全不同,当页面处理未激活的状态下,该页面的屏幕刷新任务也会被系统暂停,因此跟着系统步伐走的requestAnimationFrame也会停止渲染,当页面被激活时,动画就从上次停留的地方继续执行,有效节省了CPU开销。

  • 函数节流:在高频率事件(resize,scroll等)中,为了防止在一个刷新间隔内发生多次函数执行,使用requestAnimationFrame可保证每个刷新间隔内,函数只被执行一次,这样既能保证流畅性,也能更好的节省函数执行的开销。一个刷新间隔内函数执行多次时没有意义的,因为显示器每16.7ms刷新一次,多次绘制并不会在屏幕上体现出来。

第八问:web计时,你知道该怎么计算首屏,白屏时间吗?

白屏时间: 白屏时间指的是浏览器开始显示内容的时间。因此我们只需要知道是浏览器开始显示内容的时间点,即页面白屏结束时间点即可获取到页面的白屏时间。

计算白屏时间 因此,我们通常认为浏览器开始渲染 标签或者解析完 标签的时刻就是页面白屏结束的时间点。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>白屏</title>
  <script type="text/javascript">
    // 不兼容performance.timing 的浏览器,如IE8
    window.pageStartTime = Date.now();
  </script>
  <!-- 页面 CSS 资源 -->
  <link rel="stylesheet" href="common.css">
  <link rel="stylesheet" href="page.css">
  <script type="text/javascript">
    // 白屏时间结束点
    window.firstPaint = Date.now();
  </script>
</head>
<body>
  <!-- 页面内容 -->
</body>
</html>
Salin selepas log masuk

因此白屏时间则可以这样计算出:

可使用 Performance API 时:

白屏时间 = firstPaint - performance.timing.navigationStart;

不可使用 Performance API 时:

白屏时间 = firstPaint - pageStartTime; //虽然我们知道这并不准确,毕竟DNS解析,tcp三次握手等都没计算入内。

首屏时间: 首屏时间是指用户打开网站开始,到浏览器首屏内容渲染完成的时间。对于用户体验来说,首屏时间是用户对一个网站的重要体验因素。通常一个网站,如果首屏时间在5秒以内是比较优秀的,10秒以内是可以接受的,10秒以上就不可容忍了。超过10秒的首屏时间用户会选择刷新页面或立刻离开。

通常计算首屏的方法有

  • 首屏模块标签标记法

  • 统计首屏内加载最慢的图片的时间

  • 自定义首屏内容计算法

1、首屏模块标签标记法

首屏模块标签标记法,通常适用于首屏内容不需要通过拉取数据才能生存以及页面不考虑图片等资源加载的情况。我们会在 HTML 文档中对应首屏内容的标签结束位置,使用内联的 JavaScript 代码记录当前时间戳。如下所示:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>首屏</title>
  <script type="text/javascript">
    window.pageStartTime = Date.now();
  </script>
  <link rel="stylesheet" href="common.css">
  <link rel="stylesheet" href="page.css">
</head>
<body>
  <!-- 首屏可见模块1 -->
  <div></div>
  <!-- 首屏可见模块2 -->
  <div></div>
  <script type="text/javascript">
    window.firstScreen = Date.now();
  </script>
  <!-- 首屏不可见模块3 -->
  <div></div>
    <!-- 首屏不可见模块4 -->
  <div></div>
</body>
</html>
Salin selepas log masuk

此时首屏时间等于 firstScreen - performance.timing.navigationStart;

事实上首屏模块标签标记法 在业务中的情况比较少,大多数页面都需要通过接口拉取数据才能完整展示,因此我们会使用 JavaScript 脚本来判断首屏页面内容加载情况。

2、统计首屏内图片完成加载的时间

通常我们首屏内容加载最慢的就是图片资源,因此我们会把首屏内加载最慢的图片的时间当做首屏的时间。

由于浏览器对每个页面的 TCP 连接数有限制,使得并不是所有图片都能立刻开始下载和显示。因此我们在 DOM树 构建完成后将会去遍历首屏内的所有图片标签,并且监听所有图片标签 onload 事件,最终遍历图片标签的加载时间的最大值,并用这个最大值减去 navigationStart 即可获得近似的首屏时间。

此时首屏时间等于 加载最慢的图片的时间点 - performance.timing.navigationStart; //首屏时间尝试: //1,获取首屏基线高度 //2,计算出基线dom元素之上的所有图片元素 //3,所有图片onload之后为首屏显示时间 //

function getOffsetTop(ele) {
    var offsetTop = ele.offsetTop;
    if (ele.offsetParent !== null) {
        offsetTop += getOffsetTop(ele.offsetParent);
    }
    return offsetTop;
}


var firstScreenHeight = win.screen.height;
var firstScreenImgs = [];
var isFindLastImg = false;
var allImgLoaded = false;
var t = setInterval(function() {
var i, img;
if (isFindLastImg) {
if (firstScreenImgs.length) {
for (i = 0; i < firstScreenImgs.length; i++) {
img = firstScreenImgs[i];
if (!img.complete) {
allImgLoaded = false;
break;
} else {
allImgLoaded = true;
}
}
} else {
allImgLoaded = true;
}
if (allImgLoaded) {
collect.add({
firstScreenLoaded: startTime - Date.now()
});
clearInterval(t);
}
} else {
var imgs = body.querySelector(&#39;img&#39;);
for (i = 0; i<imgs.length; i++) {
img = imgs[i];
var imgOffsetTop = getOffsetTop(img);
if (imgOffsetTop > firstScreenHeight) {
isFindLastImg = true;
break;
} else if (imgOffsetTop <= firstScreenHeight && !img.hasPushed) {
img.hasPushed = 1;
firstScreenImgs.push(img);
}
}
}
}, 0);
doc.addEventListener(&#39;DOMContentLoaded&#39;, function() {
var imgs = body.querySelector(&#39;img&#39;);
if (!imgs.length) {
isFindLastImg = true;
}
});




win.addEventListener(&#39;load&#39;, function() {
allImgLoaded = true;
isFindLastImg = true;
if (t) {
clearInterval(t);
}
collect.log(collect.global);
});
Salin selepas log masuk

解释一下思路,大概就是判断首屏有没有图片,如果没图片就用domready时间,如果有图,分2种情况,图在首屏,图不在首屏,如果在则收集,并判断加载状态,加载完毕之后则首屏完成加载,如果首屏没图,找到首屏下面的图,立刻触发首屏完毕。可以想象这么做前端收集是不准的,但是可以确保最晚不会超过win load,所以应该还算有些意义。。没办法,移动端很多浏览器不支持performance api,所以土办法前端收集,想出这么个黑魔法,在基线插入节点收集也是个办法,但是不友好,而且现在手机屏幕这么多。。

3、自定义模块内容计算法

由于统计首屏内图片完成加载的时间比较复杂。因此我们在业务中通常会通过自定义模块内容,来简化计算首屏时间。如下面的做法:

  • 忽略图片等资源加载情况,只考虑页面主要 DOM
  • 只考虑首屏的主要模块,而不是严格意义首屏线以上的所有内容

实际上用performance.timing来计算首屏加载时间与白屏时间非常简单与精确。不过目前只支持IE10和chrome 贴下其API的使用

var navigationStart = performance.timing.navigationStart;
//1488984540668
console.log(navigationStart);

//Wed Mar 08 2017 22:49:44 GMT+0800 (中国标准时间)
console.log(new Date(new Date(navigationStart)));
复制代码
  redirectStart:到当前页面的重定向开始的时间。但只有在重定向的页面来自同一个域时这个属性才会有值;否则,值为0
  redirectEnd:到当前页面的重定向结束的时间。但只有在重定向的页面来自同一个域时这个属性才会有值;否则,值为0

console.log(performance.timing.redirectStart);//0
console.log(performance.timing.redirectEnd);//0
  fetchStart:开始通过HTTP GET取得页面的时间

console.log(performance.timing.fetchStart);//1488984540668
  domainLookupStart:开始査询当前页面DNS的时间,如果使用了本地缓存或持久连接,则与fetchStart值相等
  domainLookupEnd:査询当前页面DNS结束的时间,如果使用了本地缓存或持久连接,则与fetchStart值相等

console.log(performance.timing.domainLookupStart);//1488984540670
console.log(performance.timing.domainLookupEnd);//1488984540671
  connectStart:浏览器尝试连接服务器的时间
  secureConnectionStart:浏览器尝试以SSL方式连接服务器的时间。不使用SSL方式连接时,这个属性的值为0 
  connectEnd:浏览器成功连接到服务器的时间

console.log(performance.timing.connectStart);//1488984540671
console.log(performance.timing.secureConnectionStart);//0
console.log(performance.timing.connectEnd);//1488984540719
  requestStart:浏览器开始请求页面的时间
  responseStart:浏览器接收到页面第一字节的时间
  responseEnd:浏览器接收到页面所有内容的时间

console.log(performance.timing.requestStart);//1488984540720
console.log(performance.timing.responseStart);//1488984540901
console.log(performance.timing.responseEnd);//1488984540902
  unloadEventStart:前一个页面的unload事件开始的时间。但只有在前一个页面与当前页面来自同一个域时这个属性才会有值;否则,值为0
  unloadEventEnd:前一个页面的unload事件结束的时间。但只有在前一个页面与当前页面来自同一个域时这个属性才会有值;否则,值为0

console.log(performance.timing.unloadEventStart);//1488984540902
console.log(performance.timing.unloadEventEnd);//1488984540903
  domLoading:document.readyState变为"loading"的时间,即开始解析DOM树的时间
  domInteractive:document.readyState变为"interactive"的时间,即完成完成解析DOM树的时间
  domContentLoadedEventStart:发生DOMContentloaded事件的时间,即开始加载网页内资源的时间
  domContentLoadedEventEnd:DOMContentLoaded事件已经发生且执行完所有事件处理程序的时间,网页内资源加载完成的时间
  domComplete:document.readyState变为"complete"的时间,即DOM树解析完成、网页内资源准备就绪的时间

console.log(performance.timing.domLoading);//1488984540905
console.log(performance.timing.domInteractive);//1488984540932
console.log(performance.timing.domContentLoadedEventStart);//1488984540932
console.log(performance.timing.domContentLoadedEventEnd);//1488984540932
console.log(performance.timing.domComplete);//1488984540932
  loadEventStart:发生load事件的时间,也就是load回调函数开始执行的时间 
  loadEventEnd:load事件已经发生且执行完所有事件处理程序的时间

console.log(performance.timing.loadEventStart);//1488984540933
console.log(performance.timing.loadEventEnd);//1488984540933
Salin selepas log masuk

第九问:你知道web Worker吗?

多线程技术在服务端技术中已经发展的很成熟了,而在Web端的应用中却一直是鸡肋 在新的标准中,提供的新的WebWork API,让前端的异步工作变得异常简单。 使用:创建一个Worker对象,指向一个js文件,然后通过Worker对象往js文件发送消息,js文件内部的处理逻辑,处理完毕后,再发送消息回到当前页面,纯异步方式,不影响当前主页面渲染。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <script type="text/javascript">
        //创建线程 work对象
        var work = new Worker("work.js");      //work文件中不要存在跟ui代码
        //发送消息
        work.postMessage("100");
        // 监听消息
        work.onmessage = function(event) {
            alert(event.data);
        };
    </script>
</head>
<body>
 
</body>
</html>
Salin selepas log masuk

work.js

  onmessage = function (event) {
    //从1加到num
    var num = event.data;
    var result = 0;
    for (var i = 1; i <= num; i++) {
        result += i;
    }
    postMessage(result);
}
Salin selepas log masuk

(学习视频分享:web前端入门jQuery视频教程

Atas ialah kandungan terperinci [Kemahiran Lanjutan] Sembilan soalan temuduga hadapan untuk membantu anda menyatukan pengetahuan anda!. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:cnblogs.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan