1. 程式人生 > 遊戲攻略 >《原神攻略》堇庭華彩月章星句第三天拍照攻略 蒙德特產拍照地點

《原神攻略》堇庭華彩月章星句第三天拍照攻略 蒙德特產拍照地點

JavaScript

原型鏈

每建立一個函式,解析器都會想函式中新增一個prototype原型屬性,這個prototype屬性對應著一個物件,這個物件就是原型物件
如果該函式是普通函式呼叫,則prototype沒作用
如果該函式是以建構函式呼叫,則建立的物件中都會有一個隱含的屬性,指向該建構函式的原型物件,通過prototype來訪問該屬性
物件.hasOwnProperty(屬性)        //物件自身中是否包含某種屬性
原型物件也是物件,所以也有原型 object物件沒有原型
物件要使用某個屬性或方法,會現在自身尋找→原型物件中尋找→原型物件的原型中尋找......直到object物件原型

陣列

會影響原陣列的陣列方法:push,pop,shift,unshift,reverse,splice,sort
      <script>
       let arr = [1,2,3,4,5]
         //返回擷取從0到3組成的新陣列
       console.log(arr.slice(0,3));
        //返回刪除索引0開始的1個元素 並用22,33插入刪除的位置
       console.log(arr.splice(0,1,'22','33'));  
     </script>
陣列去重
 <script>
     let arr = [1, 2, 2, 2, 3, 4, 5, 2, 3, 1, 2, 0]
     for (let i = 0; i < arr.length; i++) {
       for (let j = i + 1; j < arr.length; j++) {
         if (arr[i] == arr[j]) {
           arr.splice(j, 1)
           j--
        }
      }
    }
     console.log(arr.sort())
   </script>

######

 

this的情況

一、隱式繫結 沒有 物件.函式 指向window

--函式呼叫時前面並未指定任何物件,這種情況下this指向全域性物件window。
function fn1() {
   let fn2 = function () {
       console.log(this); //window
       fn3();
  };
   console.log(this); //window
   fn2();
};

function fn3() {
   console.log(this); //window
};

fn1();
--如果函式呼叫時,前面存在呼叫它的物件,那麼this就會隱式繫結到這個物件上
函式呼叫前存在多個物件,this指向距離呼叫自己最近的物件
function fn() {
   console.log(this.name);
};
let obj = {
   name: '行星飛行',
   func: fn,
};
let obj1 = {
   name: '聽風是風',
   o: obj
};
obj1.o.func() //行星飛行

二、 隱式丟失

在特定情況下會存在隱式繫結丟失的問題,最常見的就是作為引數傳遞以及變數賦值
var name = '行星飛行';
let obj = {
   name: '聽風是風',
   fn: function () {
       console.log(this.name);
  }
};

function fn1(param) {
   param();
};
fn1(obj.fn);//行星飛行
// obj.fn 也就是一個函式傳遞進 fn1 中執行,單純傳遞了一個函式而已,this並沒有跟函式綁在一起,所以this丟失這裡指向了window。
var name = '行星飛行';
let obj = {
   name: '聽風是風',
   fn: function () {
       console.log(this.name);
  }
};
let fn1 = obj.fn;
fn1(); //行星飛行

三、顯式繫結(通過call、apply以及bind方法改變this的行為)

call與apply讓函式從被動變主動,函式能主動選擇自己的上下文,以此方法改變this指向時,指向引數提供的是null或者undefined,那麼 this 將指向全域性物件。
let obj1 = {
   name: '聽風是風'
};
let obj2 = {
   name: '時間跳躍'
};
var name = '行星飛行';

function fn() {
   console.log(this.name);
};
fn.call(obj1); //聽風是風
fn.apply(obj2); //時間跳躍
fn.call(undefined); //行星飛行
fn.apply(null); //行星飛行
fn.bind(undefined)(); //行星飛行

call、apply與bind有什麼區別?

1.call、apply與bind都用於改變this繫結,但call、apply在改變this指向的同時還會執行函式,而bind在改變this後是返回一個全新的boundFcuntion繫結函式,這也是為什麼上方例子中bind後還加了一對括號 ()的原因。
2.bind屬於硬繫結,返回的 boundFunction 的 this 指向無法再次通過bind、apply或 call 修改;call與apply的繫結只適用當前呼叫,呼叫完就沒了,下次要用還得再次綁。
let obj1 = {
   name: '聽風是風'
};
let obj2 = {
   name: '時間跳躍'
};
var name = '行星飛行';

function fn() {
   console.log(this.name);
};
fn.call(obj1); //聽風是風
fn(); //行星飛行
fn.apply(obj2); //時間跳躍
fn(); //行星飛行
let boundFn = fn.bind(obj1);//聽風是風
boundFn.call(obj2);//聽風是風
boundFn.apply(obj2);//聽風是風
boundFn.bind(obj2)();//聽風是風
3.call與apply功能完全相同,唯一不同的是call方法傳遞函式呼叫形參是以雜湊形式,而apply方法的形參是一個數組。在傳參的情況下,call的效能要高於apply,因為apply在執行時還要多一步解析陣列。
let obj = {
   name: '聽風是風'
};

function fn(age,describe) {
   console.log(`我是${this.name},我的年齡是${age},我非常${describe}!`);
};
fn.call(obj,'26','帥');//我是聽風是風,我的年齡是26,我非常帥
fn.apply(obj,['26','帥']);//我是聽風是風,我的年齡是26,我非常帥

四、new繫結

function Fn(){
   this.name = '聽風是風';
};
let echo = new Fn();
echo.name//聽風是風

五、this的繫結優先順序

顯式繫結 > 隱式繫結 > 預設繫結

new繫結 > 隱式繫結 > 預設繫結

六、箭頭函式的this

箭頭函式中沒有this,箭頭函式的this指向取決於外層作用域中的this,外層作用域或函式的this指向誰,箭頭函式中的this便指向誰。一旦箭頭函式的this繫結成功,也無法被再次修改,可以通過修改箭頭函式的外層作用域達到修改箭頭函式的this。
function fn() {
   return () => {
       console.log(this.name);
  };
};
let obj1 = {
   name: '聽風是風'
};
let obj2 = {
   name: '時間跳躍'
};
fn()
fn.call(obj1)(); // fn this指向obj1,箭頭函式this也指向obj1
fn.call(obj2)(); //fn this 指向obj2,箭頭函式this也指向obj2

 

 

Math
Math.ceil(浮點數) 小數向上取整
Math.floor(浮點數) 小數向下取整
Math.round(浮點數) 小數四捨五入
Math.max(數字,數字,數字) 取數字們中最小的
Math.max(數字,數字,數字) 取數字們中最大的
生成一個x,y之間的隨機數
Math.round(Math.random()*(y-x)+x)

樣式

獲取當前元素樣式值:元素.currentStyle.樣式名 IE瀏覽器高光時刻
getComputedStyle(元素,null).樣式名 其他瀏覽器
 <script>
     // obj:元素   name:樣式名       獲取元素對應的樣式值
      function getStyle(obj,name){
        if(window.getComputedStyle){
         return getComputedStyle(obj,null)[name]
        }else{
          return obj.currentStyle[name]  //IE專屬
        }
      }
   </script>

事件物件

當事件的響應函式被觸發時,瀏覽器每次都會將一個事件物件作為實參event傳遞進響應函式
盒子隨著滑鼠移動而移動 clientX/Y pageX/Y 相對於可視視窗/整個頁面的滑鼠位置

事件引數的相容

event = event||window.event
<!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;
    }
     #box {
       width: 200px;
       height: 200px;
       background-color: cadetblue;
       position: absolute;
    }
   </style>
 </head>
 <body>
   <script type="text/javascript">
     window.onload = function () {
       var box = document.querySelector('#box')
       document.onmousemove = function (event) {
         var left = event.clientX
         var top = event.clientY
         box.style.left = left + 'px'
         box.style.top = top + 'px'
      }
    }
   </script>
   <div id="box"></div>
 </body>
</html>

事件冒泡

所謂冒泡指的就是事件的向上傳導,當後代元素的事件被觸發時,其祖先元素的相同事件也會被觸發

取消事件冒泡

event.cancelBubble = true
event.target 當前觸發事件的物件

事件委派

要實現只繫結依次事件,即可應用到多個元素上,即使元素是後新增的
--將事件繫結到元素的共同的祖先元素,後代元素事件通過冒泡傳遞給祖先元素
--祖先元素使用event.target.className=='name'接受期望元素繫結,其餘不繫結
--減少繫結次數,提高程式效能
<!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;
    }
     ul{
       background-color:cadetblue;
    }
   </style>
 </head>
 <body>
   <button id="btn">點選新增</button>
   <ul>
     <li><a href="#" class="link">超連結1</a></li>
     <li><a href="#" class="link">超連結2</a></li>
     <li><a href="#" class="link">超連結3</a></li>
   </ul>
   <script type="text/javascript">
     window.onload = function () {
       let btn = document.querySelector('#btn')
       var ul = document.querySelector('ul')
       btn.onclick = function () {
         var li = document.createElement('li')
         li.innerHTML = `<a href='#' class='link'>新建</a>`
         ul.appendChild(li)
      }
       ul.onclick = function (e) {
         if (e.target.className == 'link') {
           alert('你好啊')
        }
      }
    }
   </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;
    }
     #box {
       width: 200px;
       height: 200px;
       background-color: cadetblue;
       position: absolute;
    }
   </style>
 </head>
 <body>
   <div id="box"></div>
   <script type="text/javascript">
     window.onload = function () {
       let box = document.querySelector('#box')
       box.onmousedown = function (e) {
         // 實現滑鼠拖動點在點選處點
         var ol = e.clientX - box.offsetLeft
         var ot = e.clientY - box.offsetTop
         document.onmousemove = function (e) {
           var left = e.clientX - ol
           var top = e.clientY - ot
           box.style.left = left + 'px'   //記得單位
           box.style.top = top + 'px'
        }
         document.onmouseup = function () {
           // 取消滑鼠移動事件 就固定下來
           document.onmousemove = null
           document.onmouseup = null
        }
      }
    }
   </script>
 </body>
</html>

 

鍵盤事件

String.fromCharCode(數字) 鍵盤AC碼轉為字元
    <script type="text/javascript">
       document.onkeydown=function(e){
       //String.fromCharCode(數字)     數字轉字元
       console.log(String.fromCharCode(e.keyCode));
      }
   </script>
方塊隨著方向鍵移動練習
<!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;
    }
     #box {
       width: 200px;
       height: 200px;
       background-color: cadetblue;
       position: absolute;
    }
   </style>
 </head>
 <body>
   <div id="box"></div>
   <script type="text/javascript">
     window.onload = function () {
       var box = document.querySelector('#box')
       document.onkeydown = function (e) {
         event = event || window.event
         var speed = 10
         if (e.ctrlKey) {
           speed = 50
        }
         switch (e.keyCode) {
           case 38:
             box.style.top = box.offsetTop - speed + 'px'
             break
           case 37:
             box.style.left = box.offsetLeft - speed + 'px'
             break
           case 40:
             box.style.top =box.offsetTop + speed + 'px'
             break
           case 39:
             box.style.left = box.offsetLeft + speed + 'px'
        }
      }
    }
   </script>
 </body>
</html>

BOM

window:整個視窗
navigator:視窗資訊
location:導航條資訊
history:前進後退鍵資訊
screen:螢幕資訊

Json

本質就是特殊格式的字串使得所有語言都能識別和轉化,主要用於資料互動
Json物件 '{"屬性名1":"屬性值1","屬性名2":"屬性值2"......}' 屬性名值都要用雙引號包裹
Json陣列 '[1,2,3,4.....]'
方法: Json.parse(Json物件) 將Json物件轉化為Js物件
Json.stringfy(Js物件) 將Js物件轉化為Json物件
eval函式 能夠用來執行一段字串形成的js程式碼,並返回結果

如果eval中會將{}識別為程式碼塊 用()包裹就不會被識別為程式碼塊

    <script type="text/javascript">
     let str = "alert('hello')"
     eval(“("+str+")”)    //彈出hello
   </script>

 

JavaScript高階

資料型別

typeof 返回資料型別的字串表示 不能判斷null和object object和array
    <script type="text/javascript">
     let str = 'xy'
     console.log(typeof str === 'string')  //true
     console.log(typeof str === String)  //false
   </script>
A instanceof B A是否為B的例項 如果B函式的顯示原型物件在A物件的原型鏈上則為true 反之false
 VC    <script type="text/javascript">
     let obj = { name: 'wkq', age: 23 }
     console.log(obj instanceof Object);   //true
   </script>
undefined和null的區別

undefined是定義但未賦值,null是定義賦值但值為null

何時使用null

初始時,物件賦值為null,用null表示將要賦值為物件

結束時 物件賦值為null 讓物件成為垃圾物件被處理

資料(堆資料)|記憶體|變數(棧索引)

1、資料是儲存在記憶體代表特定資訊的東東
例如:var a = '基本資料/物件|方法/變數' a儲存的是資料/物件|方法地址/變數記憶體內容
2、記憶體是記憶體條通電後產生的可儲存資料的空間 斷電後空間和資料都消失
3、變數=變數名+變數值 對應一塊小記憶體 變數名用來查詢對應的記憶體 變數值就是記憶體中儲存的資料

回撥函式

定義了 沒有呼叫 最終執行了

IIFE 函式立即執行表示式|匿名函式自呼叫

作用:隱藏實現,不會汙染外部名稱空間 可以暴露方法
<script type="text/javascript">
   // 函式自呼叫
    (function(){
       var a =3
       console.log(a);   //3
    })()
     var a = 4
     console.log(a);     //4
     
     // ;使得不會認為是整體
    ;(function(){
       var a =1
       function test(){
         console.log(++a);
      }
       window.$ = function(){
         return {
           test:test       //返回物件 對外暴露test方法
        }
      }
    })()
      $().test()
   </script>

原型

*每個函式定義時自動新增prototype屬性,預設指向原型物件(空的object)
*原型物件中有個屬性constructor,指向函式物件
    <script type="text/javascript">
     console.log(Date.prototype.constructor === Date) //true
   </scripWt>
*可以給原型物件新增屬性(方法)
*每個物件建立時自動新增 __proto__ 屬性,預設值為建構函式的prototype屬性值
    <script type="text/javascript">
      function Fn(){

      }
      let fn = new Fn()
      console.log(Fn.prototype===fn.__proto__); //true
   </script>

原型鏈

物件要使用某個屬性或方法,會現在自身尋找→原型物件中尋找→原型物件的原型中尋找......直到object物件原型

原型繼承

建構函式的例項物件自動擁有建構函式原型物件的屬性和方法,利用的就是原型鏈
例項的隱式原型等於構造的顯示原型 二者指向同一個原型物件(空的object)
如果顯示原型重新指向,會斷開之前指向的原型物件,指向新的原型物件。而隱式原型物件依然指向之前的原型物件,不會隨著顯示原型的重新指向而改變指向
    <script type="text/javascript">
     function A() {}
     A.prototype.n = 1
     var b = new A()
     A.prototype ={
       n:2,
       m:3
    }
     var c = new A()
     console.log(b.n,b.m,c.n,c.m); //1 undefined 2 3
   </script>
原型鏈上沒有 例項的隱式原型→Function的顯示原型的路徑 如果例項訪問Function上的方法 會報錯
    <script type="text/javascript">
   function F(){
     Object.prototype.a = function(){
       console.log('a()');
    }
     Function.prototype.b = function(){
       console.log('b()');
    }
  }
   var f = new F()
   f.a()
   // f.b()
   F.a()
   F.b()
   console.log(F);
     console.log(Object.prototype);
     console.log(Function.prototype);     // ƒ () { [native code] }
     console.log(Function instanceof Object);   //true   函式是物件的例項
   </script>

變數提升與函式提升 先執行變數提升再執行函式提升

變數提升
    <script type="text/javascript">
   var a =3
   function fn(){
     console.log(a);
     var a =4
  }
   fn()      //undefined
   </script>

相當於

    <script type="text/javascript">
     var a =3
     function fn() {
        var a
       console.log(a)
       a = 4
    }
     fn() //undefined
   </script>
函式提升
  <script type="text/javascript">
     fn()      //fn() 函式提升
     function fn(){
       console.log('fn()');
    }
   </script>

執行上下文

當前程式碼執行環境,執行程式碼需要哪些資料提前準備好再開始執行

 

    <script type="text/javascript">
     /* 測試一 */
     console.log('global begin:' + i) //undefined
     var i = 1
     foo(1)
     function foo(i) {
       if (i == 4) {
         return
      }
       console.log('foo() begin:' + i)
       foo(i + 1)
       console.log('foo() end:' + i)
    }
     console.log('global end:' + i)
     /* 測試二 */
     var c = 1
     function c(c) {
       console.log(c)  
    }
     c(2)     //報錯  
//相當於
  var c
      function c(c) {
       console.log(c)  
    }
c=1
c(2)   //此時c=1 不是一個方法所以報錯
     /* 測試三 */
     if (!(b in window)) {
       var b = 1
    }
     console.log(b) //undefined
   </script>

作用域和作用域鏈

作用域只能向外查詢,不能向內查詢。當需要某個屬性時,向外找最近的祖先作用域裡的同名屬性
<script type="text/javascript">
     var a =10,b=20
     function fn(x){
       var a = 100,c=300
       console.log('fn()',a,b,c,x);
       function bar(x){
         var a =1000,d=400
         console.log('bar()',a,b,c,d,x);
      }
       bar(100)      //1000,20,300,400,100
       bar(200)      //1000,20,300,400,200
    }
     fn(10)      //100,20,300,10
   </script>
函式呼叫函式的情況下,考慮被呼叫函式的作用域向外
 <script type="text/javascript">
     var x =10
     function fn(){
       console.log(x);
    }
     function show(f){
       var x =20
       f()
    }
     show(fn) //10
   </script>
物件屬性名 不包括在函式作用域內
<script type="text/javascript">
     var fn = function () {
       console.log(fn)
    }
     fn()      //fn()
     var obj = {
       fn2: function () {
         console.log(fn2)
      },
    }
     obj.fn2() //錯誤   函式內部作用域並沒有fn2
   </script>

閉包

定義:就是包含被引用變數的物件

巢狀情況下 內部函式引用了外部函式或變數時,產生閉包
將函式作為另一個函式的返回值 產生閉包
將函式作為實參傳遞給另一個函式呼叫 產生閉包
  <body>
   <button>按鈕一</button>
   <button>按鈕二</button>
   <button>按鈕三</button>
   <script type="text/javascript">
     var btns = document.getElementsByTagName('button')
     for (let i = 0,length =btns.length; i < length; i++) {
       btns[i].addEventListener('click', function () {
         alert('第'+(i+1)+'按鈕被按了')      //捕獲i i在function之外
      })
    }
   </script>
 </body>

作用

使用函式內部的變數在函式執行完後,仍然存活在記憶體中(延長區域性變數的生命週期
讓函式外部可以操作到函式內部(區域性變數)的資料

生命週期

產生:巢狀內部函式定義完成後產生
死亡:包含閉包的函式物件成為垃圾物件時

自定義JS模組

index.js
(function mymodule(){
   var xy ='wkqXY'
   function toUp(){
       console.log('toUP'+xy.toUpperCase());
  }
   function toLow(){
       console.log('toLow'+xy.toLowerCase());
  }
    window.mymodule={ //放在window上 匯入該js檔案即可使用
       toUp,
       toLow
    }  
})()
index.html
  <script src="./index.js"></script>
 <body>
   <script type="text/javascript">
     mymodule.toUp()
     mymodule.toLow()
   </script>
 </body>

缺點

記憶體洩露
函式執行完後,函式內的區域性變數沒有釋放,佔用記憶體時間會變長 解決:及時釋放
記憶體洩露多了就會導致記憶體溢位
意外的全域性變數/定時器沒有清理/閉包都會導致記憶體洩露
記憶體溢位
當程式執行需要的記憶體超過了剩餘的記憶體,就會丟擲記憶體溢位的錯誤

禿頂題

    <script type="text/javascript">
     function fun(n,o){
       console.log(o);
       return {
         fun:function(m){
           return fun(m,n)
        }
      }
    }
     var a = fun(0)   //undefined
     a.fun(1)    
     a.fun(2)
     a.fun(3)
     var b =fun(0).fun(1).fun(2).fun(3)
     var c =fun(0).fun(1)
     c.fun(2)
     c.fun(3)
   </script>

返回一個物件的函式就是工廠函式

程序和執行緒

程序:程式的一次執行,它會佔用一片獨有的記憶體空間 程序之間相互獨立
多程序:一應用程式可以同時啟用多個例項執行
執行緒:是程序內的一個獨立執行單元,CPU最小的排程單元
單執行緒:
優:順序程式設計簡單易懂 缺:效率低
多執行緒:
優:提升CPU利用率 缺:建立多執行緒開銷/執行緒間切換開銷/死鎖和狀態同步問題

關於JS

JS是單執行緒執行的,
Js引擎執行程式碼的基本流程
1、先執行初始化程式碼

*設定定時器

*繫結監聽

*傳送網路請求

2、後面某個時刻執行回撥程式碼(回撥函式中的程式碼)

 

Array.filter(()=>{}) //用filter中的回撥過濾陣列中的值,返回新陣列
String.charAt(i) //返回字串的第i-1個字元
String.padStart(x,y)返回新的字串,表示用補全字元從左側補全原字串
x為字串長度,y為補全字元
String.padEnd(x,y)返回新的字串,表示用引數字串從右側補全原字串。

 未完待續....