<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## ES6 中類的定義 **** 參考答案: ~~~js // 1、類的基本定義 class Parent { constructor(name = "小白") { this.name = name; } } ~~~ ~~~js // 2、生成一個實例 let g_parent = new Parent(); console.log(g_parent); //{name: "小白"} let v_parent = new Parent("v"); // 'v'就是構造函數name屬性 , 覆蓋構造函數的name屬性值 console.log(v_parent); // {name: "v"} ~~~ ~~~js // 3、繼承 class Parent { //定義一個類 constructor(name = "小白") { this.name = name; } } class Child extends Parent {} console.log("繼承", new Child()); // 繼承 {name: "小白"} ~~~ ~~~js // 4、繼承傳遞參數 class Parent { //定義一個類 constructor(name = "小白") { this.name = name; } } class Child extends Parent { constructor(name = "child") { // 子類重寫name屬性值 super(name); // 子類向父類修改 super一定放第一行 this.type = "preson"; } } console.log("繼承", new Child("hello")); // 帶參數覆蓋默認值 繼承{name: "hello", type: "preson"} ~~~ ~~~js // 5、ES6重新定義的ES5中的訪問器屬性 class Parent { //定義一個類 constructor(name = "小白") { this.name = name; } get longName() { // 屬性 return "mk" + this.name; } set longName(value) { this.name = value; } } let v = new Parent(); console.log("getter", v.longName); // getter mk小白 v.longName = "hello"; console.log("setter", v.longName); // setter mkhello ~~~ ~~~js // 6、類的靜態方法 class Parent { //定義一個類 constructor(name = "小白") { this.name = name; } static tell() { // 靜態方法:通過類去調用,而不是實例 console.log("tell"); } } Parent.tell(); // tell ~~~ ~~~js // 7、類的靜態屬性: class Parent { //定義一個類 constructor(name = "小白") { this.name = name; } static tell() { // 靜態方法:通過類去調用,而不是實例 console.log("tell"); // tell } } Parent.type = "test"; // 定義靜態屬性 console.log("靜態屬性", Parent.type); // 靜態屬性 test let v_parent = new Parent(); console.log(v_parent); // {name: "小白"}? 沒有tell方法和type屬性 ~~~ 解析:[參考](https://es6.ruanyifeng.com/#docs/class) ## 談談你對 ES6 的理解 **** 參考答案:es6 是一個新的標準,它包含了許多新的語言特性和庫,是 JS 最實質性的一次升級。 比如'箭頭函數'、'字符串模板'、'generators(生成器)'、'async/await'、'解構賦值'、'class'等等,還有就是引入 module 模塊的概念。 箭頭函數可以讓 this 指向固定化,這種特性很有利于封裝回調函數 * (1)函數體內的 this 對象,就是定義時所在的對象,而不是使用時所在的對象。 * (2)不可以當作構造函數,也就是說,不可以使用 new 命令,否則會拋出一個錯誤。 * (3)不可以使用 arguments 對象,該對象在函數體內不存在。如果要用,可以用 Rest 參數代替。 * (4)不可以使用 yield 命令,因此箭頭函數不能用作 Generator 函數。 * async/await 是寫異步代碼的新方式,以前的方法有回調函數和 Promise。 * async/await 是基于 Promise 實現的,它不能用于普通的回調函數。async/await 與 Promise 一樣,是非阻塞的。 * async/await 使得異步代碼看起來像同步代碼,這正是它的魔力所在。 解析:[參考](https://www.cnblogs.com/heweijain/p/7073553.html) ## 說說你對 promise 的了解**** 高級前端會考 自己實現 promise 參考答案:Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件監聽——更合理和更強大。 所謂 Promise,簡單說就是一個容器,里面保存著某個未來才會結束的事件(通常是一個異步操作)的結果。從語法上說,Promise 是一個對象,從它可以獲取異步操作的消息。Promise 提供統一的 API,各種異步操作都可以用同樣的方法進行處理。 Promise 對象有以下兩個特點: 1. 對象的狀態不受外界影響。Promise 對象代表一個異步操作,有三種狀態:pending(進行中)、fulfilled(已成功)和rejected(已失敗)。只有異步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態。這也是Promise這個名字的由來,它的英語意思就是“承諾”,表示其他手段無法改變。 2. 一旦狀態改變,就不會再變,任何時候都可以得到這個結果。Promise對象的狀態改變,只有兩種可能:從pending變為fulfilled和從pending變為rejected。只要這兩種情況發生,狀態就凝固了,不會再變了,會一直保持這個結果,這時就稱為 resolved(已定型)。如果改變已經發生了,你再對Promise對象添加回調函數,也會立即得到這個結果。這與事件(Event)完全不同,事件的特點是,如果你錯過了它,再去監聽,是得不到結果的。 解析:[參考](https://es6.ruanyifeng.com/#docs/promise) ## 解構賦值及其原理 **** 參考答案: 解構賦值:其實就是分解出一個對象的解構,分成兩個步驟: 1. 變量的聲明 2. 變量的賦值 原理:ES6 變量的解構賦值本質上是“模式匹配”, 只要等號兩邊的模式相同,左邊的變量就會被賦予匹配的右邊的值,如果匹配不成功變量的值就等于 undefined 解析: 一、 數組的解構賦值 ~~~js // 對于數組的解構賦值,其實就是獲得數組的元素,而我們一般情況下獲取數組元素的方法是通過下標獲取,例如: let arr = [1, 2, 3]; let a = arr[0]; let b = arr[1]; let c = arr[2]; // 而數組的解構賦值給我們提供了極其方便的獲取方式,如下: let [a, b, c] = [1, 2, 3]; console.log(a, b, c); //1,2,3 ~~~ 1. 模式匹配解構賦值 ~~~js let [foo, [ [bar], baz ]] = [1, [ [2], 3 ]]; console.log(foo, bar, baz); //1,2,3 ~~~ 2. 省略解構賦值 ~~~js let [, , a, , b] = [1, 2, 3, 4, 5]; console.log(a, b); //3,5 ~~~ 3. 含剩余參數的解構賦值 ~~~js let [a, ...reset] = [1, 2, 3, 4, 5]; console.log(a, reset); //1,[2,3,4,5] ~~~ 其轉成 ES5 的原理如下: ~~~js var a = 1, reset = [2, 3, 4, 5]; console.log(a, reset); //1,[2,3,4,5] ~~~ 注意:如果剩余參數是對應的值為 undefined,則賦值為\[\],因為找不到對應值的時候,是通過 slice 截取的,如下: ~~~js let [a, ...reset] = [1]; console.log(a, reset); //1,[] ~~~ 其轉成 ES5 的原理如下: ~~~js var _ref = [1], a = _ref[0], reset = _ref.slice(1); console.log(a, reset); //1,[] ~~~ 4. 非數組解構成數組(重點,難點) 一條原則:要解構成數組的前提:如果等號右邊,不是數組(嚴格地說,不是可遍歷的解構),則直接報錯,例如: ~~~js let [foo] = 1; //報錯 let [foo1] = false; //報錯 let [foo2] = NaN; //報錯 let [foo3] = undefined; //報錯 let [foo4] = null; //報錯 let [foo5] = {}; //報錯 ~~~ 為什么?轉成 ES5 看下原理就一清二楚了: ~~~js var _ = 1, foo = _[0]; //報錯 var _false = false, foo1 = _false[0]; //報錯 var _NaN = NaN, foo2 = _NaN[0]; //報錯 var _undefined = undefined, foo3 = _undefined[0]; //報錯 var _ref = null; foo4 = _ref[0]; //報錯 var _ref2 = {}, foo5 = _ref2[0]; //報錯 ~~~ 5. Set 的解構賦值 先執行 new Set()去重,然后對得到的結果進行解構 ~~~js let [a, b, c] = new Set([1, 2, 2, 3]); console.log(a, b, c); //1,2,3 ~~~ 6. 迭代器解構 ~~~js function* fibs() { let a = 0; let b = 1; while (true) { yield a; [a, b] = [b, a + b]; } } let [first, second, third, fourth, fifth, sixth] = fibs(); sixth; // 5 ~~~ ### [](https://github.com/yisainan/web-interview/blob/master/content/js/es6.md#%E6%80%BB%E7%BB%93-1%E5%8F%AA%E8%A6%81%E6%9F%90%E7%A7%8D%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%85%B7%E6%9C%89-iterator-%E6%8E%A5%E5%8F%A3%E9%83%BD%E5%8F%AF%E4%BB%A5%E9%87%87%E7%94%A8%E6%95%B0%E7%BB%84%E5%BD%A2%E5%BC%8F%E7%9A%84%E8%A7%A3%E6%9E%84%E8%B5%8B%E5%80%BC)總結 1:只要某種數據結構具有 Iterator 接口,都可以采用數組形式的解構賦值。 7. 解構賦值的默認值 當變量嚴格等于 undefined 的時候,會讀取默認值,所謂的嚴格等于,就是“===” ~~~js -- -- -- -- -- let [a, b = 'default'] = [1]; console.log(a, b); //1,'default' -- -- -- -- -- let [c = 'default'] = [undefined]; console.log(c); //'default' -- -- -- -- -- function f() { console.log('aaa'); } let [x = f()] = [1]; console.log(x); //1 -- -- -- -- -- function f() { console.log('aaa'); //'aaa' } let [a, x = f()] = [1]; console.log(a, x); //1,undefined ~~~ ### [](https://github.com/yisainan/web-interview/blob/master/content/js/es6.md#%E6%80%BB%E7%BB%93-2%E5%A6%82%E6%9E%9C%E4%B8%8D%E4%BD%BF%E7%94%A8%E9%BB%98%E8%AE%A4%E5%80%BC%E5%88%99%E4%B8%8D%E4%BC%9A%E6%89%A7%E8%A1%8C%E9%BB%98%E8%AE%A4%E5%80%BC%E7%9A%84%E5%87%BD%E6%95%B0)總結 2:如果不使用默認值,則不會執行默認值的函數 二、對象的解構賦值 1. 解構賦值的舉例: ~~~js let p1 = { name: "zhuangzhuang", age: 25 }; let { name, age } = p1; //注意變量必須為屬性名 console.log(name, age); //"zhuangzhuang",25 ~~~ 其轉成 es5 的原理則為: ~~~js var _p1 = p1, name = _p1.name, age = _p1.age; console.log(name, age); //"zhuangzhuang",25 ~~~ 2. 解構賦值的別名 如果使用別名,則不允許再使用原有的解構出來的屬性名,看以下舉例則會明白: ~~~js let p1 = { name: "zhuangzhuang", age: 25 }; let { name: aliasName, age: aliasAge } = p1; //注意變量必須為屬性名 console.log(aliasName, aliasAge); //"zhuangzhuang",25 console.log(name, age); //Uncaught ReferenceError: age is not defined ~~~ 為何打印原有的屬性名則會報錯?讓我們看看轉成 es5 后的原理是如何實現的: ~~~js var _p1 = p1, aliasName = _p1.name, aliasAge = _p1.age; console.log(aliasName, aliasAge); //"zhuangzhuang",25 console.log(name, age); //所以打印name和age會報錯——“Uncaught ReferenceError: age is not defined”,但是為何只報錯age,不報錯name呢? ~~~ 只報錯 age,不報錯 name,這說明其實 name 是存在的,那么根據 js 的解析順序,當在當前作用域 name 無法找到時,會向上找,直到找到 window 下的 name, 而我們打印 window 可以發現,其下面確實有一個 name,值為“”,而其下面并沒有屬性叫做 age,所以在這里 name 不報錯,只報 age 的錯。類似 name 的屬性還有很多,比如 length 等。 3. 解構賦值的默認值 有些情況下,我們解構出來的值并不存在,所以需要設定一個默認值,例如: ~~~js let obj = { name: "zhuangzhuang" }; let { name, age } = obj; console.log(name, age); //"zhuangzhuang",undefined ~~~ 我們可以看到當 age 這個屬性并不存在于 obj 的時候,解構出來的值為 undefined,那么為了避免這種尷尬的情況,我們常常會設置該屬性的默認值,如下: ~~~js let obj = { name: "zhuangzhuang" }; let { name, age = 18 } = obj; console.log(name, age); //"zhuangzhuang",18 ~~~ 當我們取出來的值不存在,即為 undefined 的時候,則會取默認值(假設存在默認值),ES6 的默認值是使用\*\*“變量=默認值”\*\*的方式。 注意:只有當為 undefined 的時候才會取默認值,null 等均不會取默認值 ~~~js let obj = { name: "zhuangzhuang", age: 27, gender: null, //假設未知使用null isFat: false }; let { name, age = 18, gender = "man", isFat = true, hobbies = "study" } = obj; console.log(name, age, gender, isFat, hobbies); //"zhuangzhuang",27,null,false,"study" ~~~ 4. 解構賦值的省略賦值 當我們并不是需要取出所有的值的時候,其實可以省略一些變量,這就是省略賦值,如下 ~~~js let arr = [1, 2, 3]; let [, , c] = arr; console.log(c); //3 ~~~ 注意:省略賦值并不存在與對象解構,因為對象解構,明確了需要的屬性 ~~~js let obj = { name: "zhuangzhuang", age: 27, gender: "man" }; let { age } = obj; console.log(age); //27 ~~~ 5. 解構賦值的嵌套賦值(易錯點,重點,難點) ~~~js let obj = {}, arr = []; ({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true }); console.log(obj, arr); //{prop:123},[true] ~~~ 注意當解構出來是 undefined 的時候,如果再給子對象的屬性,則會報錯,如下 ~~~js let { foo: { bar } } = { baz: "baz" }; //報錯,原因很簡單,看下原理即可,如下: //原理: let obj = { baz: "baz" }; let foo = obj.foo; //foo為undefined let bar = foo.bar; //undefined的bar,可定報錯 ~~~ 6. {}是塊還是對象? 當我們寫解構賦值的時候,很容易犯一個錯誤——{}的作用是塊還是對象混淆,舉例如下: ~~~js //舉例一: let { a } = { a: "a" }; console.log(a); //'a',這個很簡單 //很多人覺得,以下這種寫法也是可以的: let a; { a } = { a: "a" }; //直接報錯,因為此時a已經聲明過了,在語法解析的時候,會將這一行的{}看做塊結構,而“塊=對象”,顯然是語法錯誤,所以正確的做法是不將大括號寫在開頭,如下: let a; ({ a } = { a: "a" }) ~~~ 7. 空解構 按照之前寫的,解構賦值,左邊則為解構出來的屬性名,當然,在這里,我們也可以不寫任何屬性名稱,也不會又任何的語法錯誤,即便這樣沒有任何意義,如下: ~~~js ({} = [true, false]); ({} = "abc"); ({} = []); ~~~ 8. 解構成對象的原則 如果解構成對象,右側不是 null 或者 undefined 即可! 之前說過,要解構成數組,右側必須是可迭代對象,但是如果解構成對象,右側不是 null 活著 undefined 即可! 三、字符串的解構賦值 字符串也是可以解構賦值的 ~~~js const [a, b, c, d, e] = "hello"; console.log(a, b, c, d, e); //'h','e','l','l','o' ~~~ 轉成 es5 的原理如下: ~~~js var _hello = "hello", a = _hello[0], b = _hello[1], c = _hello[2]; console.log(a, b, c); ~~~ 注意:字符串有一個屬性 length,也可以被解構出來,但是要注意,解構屬性一定是對象解構 ~~~js let { length } = "hello"; console.log(length); //5 ~~~ 4. 布爾值和數值的解構 布爾值和數值的解構,其實就是對其包裝對象的解構,取的是包裝對象的屬性 ~~~js { toString: s } = 123; console.log(s); //s === Number.prototype.toString { toString: s } = true; console.log(s); //s === Boolean.prototype.toString ~~~ ### [](https://github.com/yisainan/web-interview/blob/master/content/js/es6.md#%E6%80%BB%E7%BB%93%E8%A7%A3%E6%9E%84%E8%B5%8B%E5%80%BC%E7%9A%84%E8%A7%84%E5%88%99%E6%98%AF)總結:解構賦值的規則是: > 1. 解構成對象,只要等號右邊的值不是對象或數組,就先將其轉為對象。由于 undefined 和 null 無法轉為對象,所以對它們進行解構賦值,都會報錯。 > 2. 解構成數組,等號右邊必須為可迭代對象 [參考](https://blog.csdn.net/qq_17175013/article/details/81490923) ## var let 在 for 循環中的區別**** 參考答案: ~~~js //使用var聲明,得到3個3 var a = []; for (var i = 0; i < 3; i++) { a[i] = function () { console.log(i); }; } a[0](); //3 a[1](); //3 a[2](); //3 //使用let聲明,得到0,1,2 var a = []; for (let i = 0; i < 3; i++) { a[i] = function () { console.log(i); }; } a[0](); //0 a[1](); //1 a[2](); //2 ~~~ ~~~js for(var i=0;i<5;i++){ setTimeout(()=>{ console.log(i);//5個5 },100) } console.log(i);//5 console.log('=============') for(let j=0;j<5;j++){ setTimeout(()=>{ console.log(j);//0,1,2,3,4 },100) } console.log(j);//報錯 j is not defined ~~~ var是全局作用域,有變量提升的作用,所以在for中定義一個變量,全局可以使用,循環中的每一次給變量i賦值都是給全局變量i賦值。 let是塊級作用域,只能在代碼塊中起作用,在js中一個{}中的語句我們也稱為叫一個代碼塊,每次循環會產生一個代碼塊,每個代碼塊中的都是一個新的變量i; 解析:[參考](https://www.cnblogs.com/fanfanZhao/p/12179508.html) ## 模板字符串 ***** 參考答案: * 就是這種形式${varible}, 在以往的時候我們在連接字符串和變量的時候需要使用這種方式'string' + varible + 'string'但是有了模版語言后我們可以使用string${varible}string 這種進行連接。基本用途有如下: 1、基本的字符串格式化,將表達式嵌入字符串中進行拼接,用${}來界定。 ~~~js //es5 var name = "lux"; console.log("hello" + name); //es6 const name = "lux"; console.log(`hello ${name}`); //hello lux ~~~ 2、在 ES5 時我們通過反斜杠()來做多行字符串或者字符串一行行拼接,ES6 反引號(``)直接搞定。 ~~~js //ES5 var template = "hello \ world"; console.log(template); //hello world //ES6 const template = `hello world`; console.log(template); //hello 空行 world ~~~ ## 箭頭函數需要注意的地方**** 參考答案: ~~~ 箭頭函數有幾個使用注意點。 (1)函數體內的 this 對象,就是定義時所在的對象,而不是使用時所在的對象。 (2)不可以當作構造函數,也就是說,不可以使用 new 命令,否則會拋出一個錯誤。 (3)不可以使用 arguments 對象,該對象在函數體內不存在。如果要用,可以用 rest 參數代替。 (4)不可以使用 yield 命令,因此箭頭函數不能用作 Generator 函數。 ~~~ 上面四點中,第一點尤其值得注意。this 對象的指向是可變的,但是在箭頭函數中,它是固定的。 ~~~js function foo() { setTimeout(() => { console.log("id:", this.id); }, 100); } var id = 21; foo.call({ id: 42 }); // id: 42 ~~~ 解析:[參考](https://www.jianshu.com/p/bc28e4f67ef9) ## 箭頭函數和普通函數有什么區別**** 參考答案: * 函數體內的`this`對象,就是定義時所在的對象,而不是使用時所在的對象,用`call``apply``bind`也不能改變`this`指向 * 不可以當作構造函數,也就是說,不可以使用`new`命令,否則會拋出一個錯誤。 * 不可以使用`arguments`對象,該對象在函數體內不存在。如果要用,可以用`rest`參數代替。 * 不可以使用`yield`命令,因此箭頭函數不能用作`Generator`函數。 * 箭頭函數沒有原型對象`prototype` ## Promise 構造函數是同步執行還是異步執行,那么 then 方法呢?**** 參考答案: ~~~js const promise = new Promise((resolve, reject) => { console.log(1) resolve() console.log(2) }) promise.then(() => { console.log(3) }) console.log(4) ~~~ 執行結果是:1243 promise構造函數是同步執行的,then方法是異步執行的
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看