フロントエンドの総合面接の質問 1 (継続的に更新)

マップとオブジェクトの違い

ES6 は、Object に少し似た新しいデータ構造である Map クラスを提供します。

違い:

オブジェクトは基本的にハッシュ構造のキーと値のペアのコレクションです.キーとして文字列、数字、記号などの単純なデータ型しか使用できないため、大きな制限があります.

Map クラスは Object を継承し、Object 関数にいくつかの拡張を行いました. Map のキーは任意のデータ型にすることができます.

両者の違いは主に以下の点です。

同名の衝突

オブジェクトが実際にヒープ上のメモリの一部を開き、マップのキーが実際にこのメモリのアドレスを格納していることがわかります。アドレスが異なる限り、それらは 2 つの異なるキーであり、従来のオブジェクトでは明らかに不可能であった、同じ名前を持つプロパティの衝突の問題を解決します。

反復可能

Map は for...of でトラバースできるイテレータを実装しますが、Object はできません。

長さ

Map は長さを直接取得できますが、Object は取得できません。

秩序

Map に入力された要素は元の順序を維持しますが、Object は維持できません。

拡張可能

Map は省略記号構文を使用して展開できますが、Object はできません。

マップとセットの違い

==マップ== はキーと値のペアのセットの構造であり、検索速度が非常に高速です。Map の初期化には、2 次元配列が必要であるか、空の Map を直接初期化する必要があります。

Map には次のメソッドがあります。

var m = new Map(); // 空Map
m.set('Adam', 67); // 添加新的key-value
m.set('Bob', 59);
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined

キーは 1 つの値にしか対応できないため、値は複数回キーに配置されます。後続の値は前の値を上書きします

var m = new Map();
m.set('Adam', 67);
m.set('Adam', 88);
m.get('Adam'); // 88

== Set == も Map と同様にキーのセットです。ただし、 Set は値を格納せず、キーを繰り返すことができないという違いがありますセットを作成するには、配列を入力として提供するか、空のセットを直接作成する必要があります。

var s1 = new Set(); // 空Set
var s2 = new Set([1, 2, 3]); // 含1, 2, 3

重複する要素はセット内で自動的にフィルタリングされます** (注: 数字の 3 と文字列 '3' は異なる要素です)**:

var s = new Set([1, 2, 3, 3, '3']);
s; // Set {1, 2, 3, "3"}

Set には次のメソッドがあります。

//通过add(key)方法可以添加元素到Set中,可以重复添加,但不会有效果
s.add(4);
s; // Set {1, 2, 3, 4}
s.add(4);
s; // 仍然是 Set {1, 2, 3, 4}

//通过delete(key)方法可以删除元素
var s = new Set([1, 2, 3]);
s; // Set {1, 2, 3}
s.delete(3);
s; // Set {1, 2}


add(value):添加某个值,返回Set结构本身。 
delete(value):删除某个值,返回一个布尔值,表示删除是否成功。 
has(value):返回一个布尔值,表示该值是否为Set的成员。 
clear():清除所有成员,没有返回值。

要約:

1. Map オブジェクトは、JSON オブジェクトに似たキーと値のペアのコレクションですが、キーは文字列だけでなく、Map のキーになるオブジェクトなど、さまざまな種類の値にすることもできます。メソッドは次のとおりです: set get has delete

var map = new Map();
var obj = {
     
      name: '小缘', age: 14 };
map.set(obj, '小缘喵');
map.get(obj); // 小缘喵
map.has(obj); // true
map.delete(obj) ;// true
map.has(obj); // false

2. Set オブジェクトは配列に似ており、そのメンバーの値は一意です

配列のfilter、every、flatの機能は何ですか

フィルターの役割

基準を満たすすべての要素を含む新しい配列が作成されます

それぞれの役割

配列内の要素が要件を満たしているかどうかを照会し、すべてが満たされている場合は true を返し、そうでない場合は false を返します

一部の役割

要件を満たす要素が配列内にあるかどうかを照会し、それらが満たされている場合は true を返し、実行を続行しません。それ以外の場合は false を返します

フラットの役割

2 次元配列を 1 次元配列に、3 次元配列を 1 次元および 2 次元配列に変換するなど、配列をフラット化します。パラメータを受け入れます。渡されない場合、デフォルトは 1 です。これは、平坦化されるレイヤの数を意味します。

ES6 の新機能

1.let キーワード

let キーワードは、変数を宣言するために使用されます。let を使用して宣言された変数には、いくつかの特徴があります。

  1. 重複したステートメントは許可されていません
  2. ブロックスコープ
  3. 変数の巻き上げはありません(未定義の前には使用できません)
  4. スコープチェーンには影響しません

2. const キーワード

const キーワードは、定数を宣言するために使用されます。const 宣言には、次の特徴があります。

  1. 宣言は初期値を割り当てる必要があります
  2. 識別子は通常大文字です
  3. 重複したステートメントは許可されていません
  4. 値は変更できません
  5. ブロックスコープ

3. 変数分解代入

ES6 では、配列とオブジェクトから値を抽出し、特定のパターンに従って変数に値を割り当てることができます。これは、構造化代入と呼ばれます。

//1. 数组的结构
const Hua = ['小花','刘花','赵花','宋花'];
let [xiao, liu, zhao, song] = Hua;
// 结构赋值完,可以直接使用
console.log(xiao);
console.log(liu);
console.log(zhao);
console.log(song);

//2. 对象的解构
const zhao = {
    
    
    name: '赵本山',
    age: '不详',
    xiaopin: function(){
    
    
        console.log("我可以演小品");
    }
};

let {
    
    name, age, xiaopin} = zhao;
console.log(name);
console.log(age);
console.log(xiaopin);
xiaopin();

let {
    
    xiaopin} = zhao;
xiaopin();

4. テンプレート文字列

テンプレート文字列 (テンプレート文字列) は、バッククォート (`) で識別される文字列の拡張バージョンであり、次の機能を備えています。

  1. 改行文字は文字列に表示できます
  2. 変数は ${xxx} の形式で出力できます

5. オブジェクトの書き込みを簡素化する

ES6 では、オブジェクトのプロパティとメソッドとして、中括弧内に変数と関数を直接記述できます。この書き方はより簡潔です。

6. アロー機能

ES6 では、「矢印」 (=>) を使用して関数を定義できます。アロー関数を記述するには、括弧を省略する方法と中括弧を省略する方法の 2 つしかありません。(注: 独自の this はありません)

アロー関数に関する注意事項:

  1. 仮パラメータが 1 つしかない場合は、括弧を省略できます (括弧を省略します)。
  2. 関数本体にステートメントが 1 つしかない場合、中かっこは省略でき、関数の戻り値はステートメントの実行結果になります (中かっこは省略されます)。
  3. アロー関数 this は、宣言されたスコープ内の this の値を指します
  4. アロー関数はコンストラクターとしてインスタンス化できません
  5. 引数を使用できません

7.シンボル

  1. Symbol は基本的に
    ES6 を使用して、一意の値を表す新しいプリミティブ データ型 Symbol を導入します。JavaScript 言語の 7 番目のデータ型で、文字列に似たデータ型です。

シンボルの使用シナリオ: プロパティとメソッドをオブジェクトに追加する

シンボルの特徴:

Symbol の値は一意であり、名前の競合の問題を解決するために使用されます。Symbol
値は、他のデータで操作できません。Symbol
で定義されたオブジェクト プロパティは、for...in ループでトラバースできませんが、Reflect を使用できます。 ownKeys を使用して、オブジェクトのすべてのキー名を取得します。

注: 遇到唯一性的场景时要想到 Symbol

USONB you are so niubility(JavaScript七种数据类型)

U undefined

S string symbol

O object

N null number

B boolean

8.約束

Promise は、ES6 で導入された非同期プログラミングの新しいソリューションです。構文的には、Promise は非同期操作をカプセル化し、その成功または失敗の結果を取得できるコンストラクターです。

Promise コンストラクター: Promise (実行者) {}
Promise.prototype.then メソッド
Promise.prototype.catch 排他的ガード:

 //实例化 Promise 对象,成功是resolve,失败是reject
const p = new Promise(function(resolve, reject){
    
    
    setTimeout(function(){
    
    
        // let data = '数据库中的用户数据';
        // resolve(data);

        let err = '数据读取失败';
        reject(err);
    }, 1000);
});

//调用 promise 对象的 then 方法
p.then(function(value){
    
    
    console.log(value);
}, function(reason){
    
    
    console.error(reason);
})

// 发送ajax请求,接口地址: https://api.apiopen.top/getJoke
const p = new Promise((resolve, reject) => {
    
    
    //1. 创建对象
    const xhr = new XMLHttpRequest();
    //2. 初始化
    xhr.open("GET", "https://api.apiopen.top/getJ");
    //3. 发送
    xhr.send();
    //4. 绑定事件, 处理响应结果
    xhr.onreadystatechange = function () {
    
    
        //判断
        if (xhr.readyState === 4) {
    
    
            //判断响应状态码 200-299
            if (xhr.status >= 200 && xhr.status < 300) {
    
    
                //表示成功
                resolve(xhr.response);
            } else {
    
    
                //如果失败
                reject(xhr.status);
            }
        }
    }
})

//指定回调
p.then(function(value){
    
    
    console.log(value);
}, function(reason){
    
    
    console.error(reason);
});

一般的な約束の面接の質問

  1. Promise はどのような問題を解決しますか?
  2. Promise の業界実装は何ですか?
  3. Promise で一般的に使用される API は何ですか?
  4. Promise/A+ 仕様に準拠した Promise を記述できますか?
  5. イベントループ内でのPromiseの実行処理は?
  6. Promise の何が問題で、どのように修正できますか?

プロジェクトでどのような問題に遭遇しましたか? それを解決する方法

  1. プロセストークン

  2. データ駆動型のビューは即時ではありません (DOM 要素を取得するためにコンポーネントが非同期にレンダリングされません)

    解決策: 更新されたフック関数を使用してくださいthis.$nextTick() setTimeOut()

    すぐにDOMを操作したい Vueは非同期で更新

    データが更新された後、ビューの更新は非同期であるため、呼び出しが必要ですthis.$nextTick(()=>{可以拿到更新之后的DOM})

    注: v-if がある場合は使用できません

  3. バックエンドから返される大量のデータの問題について

    js の大きな数の問題: (js の安全な整数の範囲を超えて)

    バックエンドからいくつかの id 値が返されたので、その id 値を使用して応答データを要求しましたが、要求が使用できないことがわかり、バックエンドと調整したところ、数値に変換した id が一致しないことがわかりました。バックエンドによって与えられた文字列 ID

    何が原因なのか一向に解明できませんでしたが、後でBaiduに行ってみたところ、jsが2の53乗を超えるデータを正確に表現できていないことが原因であることがわかりました。

    私は再びバックエンドに行き、ID を変更するように依頼しましたが、バックエンドは変更できないと言いました

    私は自分でしか解決策を見つけることができず、後でこの問題を解決するプラグインを見つけました:npm i json-bigint

    ①輸入import jsonBig from 'json-bigint'

    ②値に変換: const obj =jsonBig.parse(JSON数据) obj.property name.toString() —>value

    大量のデータを JSON データに使用JSON.stringify(JSONBig.parse(jsonStr))----->JSON データ ----->バックエンドに渡す

Promise.all と Promise.race の違いと使い方

Promise.all

たとえば、配列内の P1 と P2 がすべて実行されると、ページが表示されます。

P2 の戻りが P1 の戻りよりも速くても、返される配列結果の順序は変わらないことに注意してください。順序は P1、P2 のままです。

Promise.all は成功配列を正常に返します

失敗したデータを返すのに失敗しました。一度失敗すると、ダウンし続けることはありません

        let p1 = Promise.resolve('aaa')
        let p2 = Promise.resolve('bbb')
        let p3 = Promise.reject('ccc')
        let p4 = Promise.resolve('ddd')
        Promise.all([p1, p2, p3, p4]).then(res => {
     
     
            console.log(res); //返回数组
        }).catch(err => {
     
     
            console.log(err);
        })

promise.race()

Promise.race は競合を意味します。つまり、 Promise.race([p1, p2, p3]) の結果がすぐに得られたものは、結果自体が成功であるか失敗であるかに関係なく、結果を返します。

使用シーン:

操作を行うとき、同时さまざまなインターフェイスから返されたデータが必要になる場合があります.返されたデータの順序を考慮するために、次を使用できますPromise.all

いくつかのサーバーはいくつかのインターフェースを提供しています同样的服务. どのインターフェースがより速いかはわからないので、それを使用できますPromise.race. どのインターフェースのデータが最初に戻ってくるか、どのインターフェースのデータを使用します.

v-modeの本質(原理)とは

v-model本質は、v-bind:value="" と @input イベントのシンタックス シュガーです。

当一个组件上面同时有value属性和input自定义事件的时候,且操作的是同一个变量,即可使用v-model来简化

如何修改v-model 自定义的默认的规则属性 通过model进行修改

 model: {
     
     
    prop: 'isFollowed',
    event: 'changed'
  }

知识点小记

less语法:@import ’ '; 一定要加引号

在main.js中引入import ,import 之间只允许有注释不许有其他语句

import导入规则:

一、下载的第三方包:import: ‘包名’ (去node_modules去找index.js文件)

二、手动导入:import: ‘./文件名’

推送提交:

git push -u origin master 的含义:

完整写法:git push --set-upstream origin master:master

解析:

master:master 是将本地master提交到远程仓库主分支master

–set-upstream 是对于每个最新的或成功推送的分支,添加上游(跟踪)引用 简写为-u (简单理解为记住本次提交信息,下次提交就可以直接git push)

origin: 就是添加的远程仓库地址

创建实例:

const request = axios.create ({})

==好处:==可以根据不同的路径去请求不同的服务器 ,如果写在main.js中会显得代码臃肿或者这种:axios.defaults.baseURL:会直接把路径写死

懒加载:

好处:提高首屏速度 Vue是单页面(只有一个html)

怎么提升加载速度?

如果使用的是原始导入方式,webpack在打包的时候会把所有的组件打包成1个js文件,在页面刚刷新的时候就把这个js加载完毕了

懒加载:webpack会把懒加载的组件单独打包成一个一个的js文件,在用户跳转到对应的组件的时候才会去加载

具名插槽:

新语法:必须带template标签包裹 v-slot:名字 简写为#名字

旧语法:在具体标签里 slot=“名字”

例:<i slot="名字"></i>

JSON数据:

双引号的格式:属性和值都是带双引号的

json データは undefined および関数をサポートしていません

オブジェクトと配列は json データに変換されます:JSON.stringfly()逆は:JSON.parse

ディープコピー:

  • ポジティブおよびデシリアライゼーション (短所: 未定義の関数データを含めることはできません)
  • 再帰によるディープコピー

カプセル化リクエスト パラメータの受け渡し要件:

  • データ①に直接以下のように記述した場合、カプセル化された関数で渡すパラメータは②になります。
//①
data(){
    
    
    return {
    
    
        a:'',
        b:''
    }
}
//②
export const login = (tel,code) => {
    
    
  return request({
    
    
    method: 'POST',
    url: '/v1_0/authorizations',
    data:{
    
    
      mobile:tel,
      code:code
    }
  })
}
  • 略記:

次のように、データにオブジェクトを書き込み、オブジェクトにデータを書き込みます。

  data () {
    
    
    return {
    
    
      user: {
    
    
        mobile: '',
        code: ''
      }
    }
  },
  
  
  //
  export const login = data => {
    
    
  return request({
    
    
    method: 'POST',
    url: '/v1_0/authorizations',
    data
  })
}

トークン値関連の知識ポイント:

最初のログイン成功後、サーバーはトークン値を返します

リフレッシュ トークンの値が失われないようにするには、データをローカル ストレージにバックアップする必要があります。window.localStorage.setItem('仓库名字',JSON.stringify())

知らせ:ローカル ストレージに格納できるのは、文字列形式のJSON.stringify()シリアル化のみです

つまり、保存時にシリアライズするJSON.stringify()

フェッチ時にデシリアライズするJSON.parse

vuex とローカル ストレージの違い:

vuex: ① vuex はレスポンシブデータ ② 一時ストレージ

ローカルストレージ:

sessionStorage: ライフ サイクル - ブラウザを閉じるとデータが消える、更新してもデータが消えない、データは現在のページで共有されている、メモリは 5M、保存されているデータは JSON データです

localStorage: ライフサイクル永久、同じブラウザ データ共有 (同じドメイン名、同じホスト名である必要があります)、メモリ サイズ 20M、保存されるデータは JSON データです

トークンはプロジェクトにどのように保存されますか?

1. 最初に vuex を保存します 2. ローカル ストレージを保存します

分解された属性名は、応答 {data} の属性名と同じでなければなりません

パスワード暗号化 (md5.js)

バックエンドでパスワード暗号化が必要な場合は、このプラグインをダウンロードする必要があります

ローカルストレージのエージング処理を行うには?

①保存トークン→タイムスタンプ追加( timer: +new Date() )

②トークンを使用する場合は、まず現在のタイムスタンプを取得 - ストレージのタイムスタンプ / 1000 / 60 (分) > 時差

③タイムアウトの場合は再度ログインするページへジャンプ タイムアウトが無ければ通常通りトークンを使用

vue の css はイメージ パスを使用します。background: url("~@/assets/banner.png");

ルーティング ジャンプ:

名前とパスの両方がルーティング ジャンプですが、名前はより適切に維持されます

ログインをクリックして別のページにジャンプします プログラムによる:@click="$router.push('/login')" これは省略形です

具体的に書かれています:

this.$router.push({
    path:'/login',
    ...需要传递的参数
})

ジャンプ後に別のページに戻る必要があります:$router.back()または: $router.go(-1)-1 で一度戻る

これを差分式に書く必要はありません

シングル ページ アプリケーション (SPA) とは:

One of the core idea of​​ Single Page Application (SPA) is to update the view without rerequest the page. 簡単に言えば、ページをロードするときに、ページ全体をロードするのではなく、指定されたコンテナー内のコンテンツのみを更新します。ほとんどの単一ページ アプリケーションでは、公式にサポートされている vue-router をお勧めします。

その中で、NetEase Music は単一ページのアプリケーションを使用しています。

Vue のルーティング実装モード: ハッシュ モードと履歴モード

ハッシュ モード:

Vue-router のデフォルトは、URL のハッシュを使用して完全な URL をシミュレートするハッシュ モードです. URL が変更されると、ページはリロードされません. # はハッシュ記号、中国名はハッシュ記号またはアンカーポイントで、ハッシュ記号の後の値はハッシュ値と呼ばれます。

ルートのハッシュ モードは、ウィンドウを使用して onhashchange イベントをリッスンすることによって実現されます, つまり、ハッシュ値はブラウザのアクションをガイドするために使用され、サーバーには影響しません. HTTP 要求にはハッシュが含まれません.値、およびハッシュ値が変更されるたびに、ブラウザのアクセス履歴にレコードが追加されます。「戻る」ボタンを使用すると、前の位置に戻ることができます。したがって、ハッシュモードはハッシュ値に応じて変化し、異なる値に応じて指定された DOM 位置に異なるデータをレンダリングします。

履歴モード:

ハッシュ モードの URL には # 記号があり、URL の外観に影響しますが、履歴モードでは # 記号は表示されません. このモードでは、history.pushState() をフルに活用して、リロードせずに URL ジャンプを完了しますページ。履歴モードを使用する場合は、mode:'history' をルーティング ルール構成に追加する必要があります。、コード例は次のとおりです。

// main.js 文件
const router = new VueRouter ({
    
    
    mode:'history',
    routes: [...]
})

HTML5 には履歴用の 2 つの新しい API がありますhistory.pushState()history.replaceState() ブラウザの履歴スタックを変更できます、および状態の変化に対するpopState イベントリスナー。

それらはすべて、状態オブジェクト (状態オブジェクト)、タイトル (タイトル)、およびアドレス (URL) という 3 つのパラメーターを受け取ります。以下に、これら 3 つのパラメータの意味を簡単に紹介します。

(1)状态对象(state object):一个JavaScript对象,与用pushState()方法创建的新历史记录条目关联。

(2)标题(title):FireFox浏览器目前会忽略该参数。为了安全性考虑,建议传一个空字符串。或者也可以传入一个简短的标题,标明将要进入的状态。

(3)地址(URL):新的历史记录条目的地址。

vue全家桶是指什么?有哪些东西?

Vue全家桶一般来说指的是脚手架vue-cli、路由vue-Router、状态管理模式vuex、Axios、elementUI等ui框架和打包工具webpack

命令包:

npm i -g nrm —切换镜像源

npm ls 查看

npm i 装包

或者 npm i -g cnpm

js文件里怎么访问vuex的数据?

导入vuex的仓库的store

请求拦截器:

作用:统一给有权限的接口注入请求头token

添加判断条件:

如果用户没有登录,token值为null,报错,所以要添加判断条件if(user && user.token){} === if(null && null.token) 如果为null 则退出判断条件

在config配置项里添加headers请求头

在请求拦截器添加headers后就可以把api/user.js中的headers注释掉了

无感刷新(响应拦截器)

短token:用来发请求,在请求头里携带,一般两小时过期

refresh_token:长token 用来获取新的短token 一般14天过期

能不能把短token过期时间加长 比如14天?

答:不能,因为涉及到安全问题,防止token被盗 (只有两个一起盗取才会泄漏信息)我们可以对登录密码加密—md5.js加密,(MD5加密本质是一个插件,调用他的方法就可以生成加密后的代码) 我们需要和后端配合(后端解密)

使用长token的思路:

  1. 用户发请求,后端返回401,说明token过期 这时要统一监测后端返回的401代码

  2. 监测到401报错,就拿长token refresh_token 发请求获取最新的token

  3. ユーザーが最後に送信したリクエストを自動的に再送信する

  4. 応答インターセプターを追加

    • 主な効果:
      • 感じずにリフレッシュ
      • バックエンドから返されたデータの統合処理
      • バックエンドデータエラーの一元処理

長いトークンを使用するためのアイデア (具体的な手順):

  1. ユーザーがリクエストを送信したとき、バックエンドが 401 を返す場合は、トークンの有効期限が切れていることを意味します. このとき、バックエンドが返す 401 コードを一律に監視する必要があります.

    • 応答インターセプターを追加し、インターセプター内のエラー報告機能でトークンの有効期限が切れているかどうかを監視および判断する必要があります. コードは次のとおりです。

      if (error.response.status === 401) {
              
              
               console.log('token过期')
      }
      
  2. 401 エラーが検出された場合は、refresh_tokenロング トークンを使用してリクエストを送信し、最新のトークンを取得します。

    • 注: リクエストは会死循环リクエスト インターセプターで設定され、古いトークンが挿入されるため、リクエストを使用して送信することはできません (リクエストを自分でカプセル化する場合)。コード例は次のとおりです。

      // 用axios发请求
          const {
              
               data } = await axios({
              
              
            url: 'http://toutiao.itheima.net/v1_0/authorizations',
            method: 'PUT',
            headers: {
              
              
              Authorization: `Bearer ${
                
                store.state.token.refresh_token}` /* 怎么拿refresh_token */
            }
          })
      
  3. 次に、新しいトークンを使用して vuex に保存し、ローカル ストレージに保存します. js ファイルで補助関数を使用することはできません, 構造化代入を使用して古いトークンを上書きすることはできません. コードは次のとおりです:

     store.commit('setUser', {
          
           ...store.state.token, token: data.data.token })
    
  4. ユーザーが最後に送信したリクエストを自動的に再送信する

    return request(error.config)
    

完全なコードは次のとおりです。

// 添加响应拦截器
request.interceptors.response.use(function (response) {
    
    
  // 2xx 范围内的状态码都会触发该函数。
  // 对响应数据做点什么
  return response
}, async function (error) {
    
    
  /* //监测token过期 */
  if (error.response.status === 401) {
    
    
    // console.log('token过期')
    // 发请求,刷新token
    // 注意:不能用request发,会死循环,因为request设置了请求拦截器,会注入老token
    // 用axios发请求
    const {
    
     data } = await axios({
    
    
      url: 'http://toutiao.itheima.net/v1_0/authorizations',
      method: 'PUT',
      headers: {
    
    
        Authorization: `Bearer ${
      
      store.state.token.refresh_token}` /* //怎么拿refresh_token */
      }
    })
    // 新token存到vuex中,存到本地存储,在js文件中不能用辅助函数
    // 利用解构赋值覆盖旧token
    store.commit('setUser', {
    
     ...store.state.token, token: data.data.token })
    // 再发一次上次发送过得请求(error里有上一次发送的地址和错误的token)
    return request(error.config)
  }
  // 超出 2xx 范围的状态码都会触发该函数。
  // 对响应错误做点什么
  return Promise.reject(error)
})

コンポーネント内のグローバル外部コンポーネント スタイルを変更するには、/deep/ を追加する必要があります (構文を少なくする必要があります) (scss 構文で ::v-deep を使用します)。

JSON.parse() は、json 形式の文字列をオブジェクトに変換するデシリアライズです (json 形式の文字列は二重引用符で囲む必要があり、その属性と値は二重引用符で囲みます) JSON.parse('sfdsfsa')。 json 形式で、エラーが報告されます

リストのスクロールが互いに影響を与えるのはなぜですか?

それら自体がスクロールしているのではなく、本文ページ全体がスクロールしているためです。

リストのスクロール位置を覚えておいてください:
方法:
各ラベル コンテンツの記事リストに独自のスクロール コンテナーを生成させ、相互に影響を与えないようにします。

記事リスト用に独自のスクロール コンテナーを生成する方法:
固定の高さを設定します。

.article-list {
    
    
height: xxx ;
overflow-y:auto;  //垂直溢出滚动
}

分解を使用してデータを追加します。

this.list = [...this.list, ...data.data.results] 最後に新しいデータを追加

高さのヒントをラベル コンテンツに追加する

部分的なコンテンツの高さを設定します。これはあらゆるデバイスに適応できます

height: calc(100vh - 274px);
  overflow-y: auto;

フィルターはグローバルおよびローカルでどのように使用されますか?

グローバル dayjs を構成した後、グローバルに使用する場合はエクスポートする必要があります

プルダウンしてデータを更新すると、空白スペースが発生します。

これは、データが十分でないためです。データはコンテンツの高さをサポートできません。

解決: コンテンツの高さをデータで埋める必要があります

相対時間の扱い方

Day.js (opens new window) は時刻と日付を処理する軽量の JavaScript ライブラリであり、Moment.js (opens new window)の API 設計はまったく同じままです。

  1. インストール
npm i dayjs
  1. utils/dayjs.js を作成します
import Vue from 'vue'
import dayjs from 'dayjs'

// 加载中文语言包
import 'dayjs/locale/zh-cn'

import relativeTime from 'dayjs/plugin/relativeTime'

// 配置使用处理相对时间的插件
dayjs.extend(relativeTime)

// 配置使用中文语言包
dayjs.locale('zh-cn')

// 全局过滤器:处理相对时间
Vue.filter('relativeTime', value => {
     
     
  return dayjs().to(dayjs(value))
})
  1. main.js で初期化をロードする
import './utils/dayjs'
  1. 使用
<span>{
     
     {
     
      article.pubdate | relativeTime }}</span>

拡大コンポーネントでローカルに使用する方法

まず、構成されたdayjsデフォルトでエクスポート

export default dayjs

次に、コンポーネントにインポートします。

// 组件内使用过滤时间的插件
import dayjs from '@/utils/dayjs'

次に、メソッドで相対時間を処理する関数を定義します。

methods: {
     
     
    relativeTime (value) {
     
      // value就是管道符前面的数据
      return dayjs().to(dayjs(value)) //to为多少年前
    }
  }

最後に、必要に応じて相対時間関数を使用します。

<span>{
     
     {
     
      article.pubdate | relativeTime }}</span>

計算されたプロパティ:

計算されたプロパティは、内部依存データの変更を監視し、依存データが変更された場合、計算されたプロパティが再実行されます

sync修飾子を使用して親コンポーネントのデータを変更します

サブアセンブリ:

sync修飾子を使用して親コンポーネントのデータを変更します

this.$emit('update:active', index)

親コンポーネント:

:actives.sync="active"

注:属性update名は後で更新されます

this.$parent:

親コンポーネントのすべてのデータとメソッドは、現在のセットでアクセスできます

ナレッジ ポイントを展開する:

  1. .sync 修飾子: 親から子にデータが渡されると、子コンポーネントは親コンポーネントのデータを変更できる 親コンポーネント
    : :プロパティ名.sync = "基本データ型" サブコンポーネント: ①props: {プロパティ名} 受信 ②対応するデータを変更親コンポーネントのthis.$emit('update:属性名', 要修改的值)(知らせsync を使用して、配列、オブジェクトなどの複雑なデータ型を操作することはできません)
  2. this.$parent は、メソッドを含む現在のコンポーネントの親コンポーネントのすべてのデータにアクセスでき、子コンポーネントで親コンポーネントのデータを変更する機能を実装でき、親コンポーネントのメソッドを呼び出すこともできます
  3. this.$children は配列で、現在のコンポーネントのすべての親子コンポーネントを取得できます
  4. this.$refs ① DOM 要素を取ることができる ② コンポーネントを取ることもできる

検索ボックスに対してどのような最適化を行う必要がありますか?

  1. アンチシェイク: 連続出力イベント、1 回のみ実行 (前回)、コア タイマー、各イベントが 1 をトリガーして前のタイマーをクリア
  2. 検索履歴の最適化: 検索されたコンテンツはローカルストレージに保存されます. ユーザーが検索するたびに, 検索されたキーワードがローカルストレージから最初にチェックされます. キーワードがあれば, ローカルストレージから直接アクセスされます.データをレンダリングする要求が行われます。

axios のパラメーターを使用した post および get リクエスト メソッドは、まったく異なります。

パラメータ付きのGETリクエストはparams

パラメータ付きの POST リクエストはdata

パッチもdata

PUTもdata

適応:

適応する、反応する

適応技術:

1. メディアクエリで html font-size + rem を切り替える

短所: 多くのメディア クエリを作成するため、面倒です。

2. Mobile Taobao flexible.js + rem flexible.js は、js を介して (onresize イベントを介して) 画面サイズの変更を監視します。 **コア アルゴリズム: **html font-size=screen width/10

3. vw/vh アダプティブ スクリーン幅 高さ ビューポート幅/10 (ビューポート単位)

postcss-pxtorem (opens new window) を使用して、px を rem に変換します。インライン スタイルを変換しません

レム計算原理: (要素ピクセル)px / ルートフォントサイズ=rem

レム適応原理(重要)

目標:幅の異なるデバイスで Web ページ要素のサイズを均等にスケーリングする効果を実現する

レムユニットサイズ

  1. ビューポートの幅に応じて異なる HTML タグのフォント サイズを設定する
  2. コードを書く、サイズはrem単位
    • 設計案に対応するデバイスのHTMLタグのフォントサイズ(基本ルートフォントサイズ)を決定する
    • デザイン案の横幅を確認→基準デバイス幅(ビューポート幅)を決定→基準ルートフォントサイズ(1/10ビューポート幅)を決定
    • rem 単位の寸法(N は rem)
      • N * 37.5 = 68 → N = 68 / 37.5
      • rem 単位のサイズ = px 単位値 / ベース ルート フォント サイズ
    • rem 単位のサイズ = px 単位値 / ベース ルート フォント サイズ (結果は小数点以下 3 桁)

(デザイン案は750pxです。1行を10分割すると1が75です。一般的には750のデザイン案を2で割ると375になり、さらに10で割ると1本が37.5になります)

ビューの原理

1. コンポーネントベース => (MVVM モデル)

従来のコンポーネント、知識の静的レンダリング、更新は DOM の操作に依存します。

Vue の中心的な概念は、データ駆動型の概念、いわゆるデータ駆動型の概念です。データが変更されると、それに応じてユーザー インターフェイスも変更され、開発者は手動で dom を変更する必要はありません。

アドバンテージ:

    不需要在代码中去频繁的操作dom了,这样提高了开发的效率,同时也避免了在操作Dom的时候出现的错误。

Vue.js のデータ ドライブは、MVVM のフレームワークを通じて実現されます.MVVM フレームワークは、主に Model、View、ViewMode の 3 つの部分で構成されます。

データ ドリブン ビュー - Vue MVVM

MVVM は Model-View-ViewModel の略で、MVC の Controller を ViewModel に進化させるものです。Model はデータモデルを表し、View は UI コンポーネントを表し、ViewModel is the bridge between the View and Modellayers. Data will bind to the ViewModel layer and automatically render the data to the page. ビューが変更されると、viewModel レイヤーはデータを更新するように通知されます。

2. Vueの応答原理

コア実装クラス:

オブザーバー: その機能は、依存関係の収集とディスパッチの更新のためにオブジェクトのプロパティにゲッターとセッターを追加することです。
Dep : 現在のレスポンシブ オブジェクトの依存関係を収集するために使用されます。サブオブジェクトを含む各レスポンシブ オブジェクトには Dep インスタンス (subs は Watcher インスタンスの配列) があり、データが変更されると、それぞれが dep.notify( を介して通知されます。 )ウォッチャー。
ウォッチャー: Observer オブジェクト、インスタンスはレンダリング ウォッチャー (render watcher)、計算属性ウォッチャー (computed watcher)、リスナー ウォッチャー (user watcher) に分けられ、
Watcher と Dep の間の 3 種類の関係、
dep はウォッチャーでインスタンス化され、dep.subs に送信されます。サブスクライバーが追加され、dep は notify を介して dep.subs をトラバースして、各ウォッチャーに更新を通知します。

コレクション(ゲッター) initStateに依存する
場合、計算された属性が初期化されると、計算されたウォッチャーが
トリガーされますコレクションinitStateに依存する場合、リスナー属性が初期化されると、
ユーザーウォッチャーの依存関係コレクションrender()のプロセスがトリガーされ、レンダー ウォッチャーの依存関係コレクションの
再レンダリングがトリガーされます。vm.render() が再度実行されると、すべてのサブ内のウォッチャーのサブスクリプションが削除され、再割り当てされます。
ディスパッチ更新(setter)
コンポーネントは、応答データを変更し、setter のロジックをトリガーし、
dep.notify() を呼び出して
すべてのサブ (Watcher インスタンス) を走査し、各ウォッチャーの update メソッドを呼び出します。

原理:

    当创建 Vue 实例时,vue 会遍历 data 选项的属性,利用 Object.defineProperty 为属性添加 getter 和 setter 对数据的读取进行劫持(getter 用来依赖收集,setter 用来派发更新),并且在内部追踪依赖,在属性被访问和修改时通知变化。

    每个组件实例会有相应的 watcher 实例,会在组件渲染的过程中记录依赖的所有数据属性(进行依赖收集,还有 computed watcher,user watcher 实例),之后依赖项被改动时,setter 方法会通知依赖与此 data 的 watcher 实例重新计算(派发更新),从而使它关联的组件重新渲染。

Object.defineProperty は応答性を実装します

リスナー オブジェクト、リスナー配列
複合オブジェクト、ディープ リスナー

const obj = {
    
    };
const data = {
    
    };
const name = 'zhangsan';
Object.defineProperty(data, 'name', {
    
    
    get: function () {
    
    
        console.log('get');
        return name;
    },
    set: function (newVal) {
    
    
        console.log('set');
        obj.name = newVal;
    }
})
console.log(data.name);
data.name = 'lisi';
console.log(obj.name);  

Object.defineProperty の欠点

詳細な監視は最後まで再帰的に行う必要があり、一度に計算量が多くなり、
新しい属性の監視や属性の削除(Vue.set Vue.delete を使用)ができず
、配列をネイティブに監視できないため、特別な処理 [配列のメソッドを書き換える ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'] これらのメソッドは、応答的に配列を変更するだけで、インデックスを直接変更しても、反応するようには変更されません]

要約:

Vue双向数据绑定的原理:
vue.js 采用数据劫持结合发布-订阅模式,通过 Object.defineproperty 来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发响应的监听回调。    
    

Vue 双方向データバインディングの原理(重要)

Vueこれがデータの双方向バインディングのフレームワークであることは誰もが知っています。双方向バインディングは 3 つの重要な部分で構成されています。

  • データ層 (モデル): アプリケーション データとビジネス ロジック
  • ビューレイヤー (View): アプリケーションの表示効果、各種 UI コンポーネント
  • ビジネス ロジック レイヤー (ViewModel): フレームワークのカプセル化の中核であり、データとビューの関連付けを担当します。

上記のレイヤード アーキテクチャ ソリューションは専門用語で言えば、MVVMここでのコントロール レイヤーのコア機能は「双方向データ バインディング」です。当然のことながら、データバインディングの原理についてさらに学ぶには、それが何であるかを理解するだけで済みます

ViewModel について

その主な責任は次のとおりです。

  • データ変更後のビューの更新
  • ビューの変更後にデータを更新する

もちろん、それには2つの主要な部分もあります

  • リスナー (オブザーバー): すべてのデータのプロパティを監視します
  • パーサー (コンパイラー): 各要素ノードの命令をスキャンして解析し、命令テンプレートに従ってデータを置き換え、対応する更新関数をバインドします。

Vue は、以下を使用して双方向のデータ バインディングを実装します。データの乗っ取りとパブリッシャー - サブスクライバー パターン. データハイジャックとは、ES5 メソッドを使用してObject.defineProperty(obj,key,val)data オプションの各属性の getter と setter をハイジャックし、データが変更されたときにサブスクライバーにメッセージを発行することで、対応するコールバックをトリガーしてビューを更新することです。

つまり、Vue インスタンスを作成するとき、データは受信データを乗っ取ります. 同時に、ビューがコンパイルされるときに、データ内のデータが使用される場所の Watcher オブジェクトを作成し、それをパブリッシャー オブジェクトに追加します。 data hijacking の getter では、乗っ取られたデータが変更された場合、publish-subscribe モードとコールバック関数を介して DOM を操作して更新するようにすべてのオブザーバーに通知し、データの双方向バインディングを実現します。

/**
 * 对Object.defineProperty()进行封装
 */
function defineReactive(obj, key, value) {
     
     
    //递归 - 对象的属性仍是对象
    observe(value);
    //变化侦测
    Object.defineProperty(obj, key, {
     
     
        get() {
     
     
            return value;
        },
        set(newVal) {
     
     
            if (newVal !== value) {
     
     
                updateView();
                value = newVal;
                observe(newVal)
            }
        }
    })
}

/**
 * 对一个对象所有属性的变化侦测
 */
function observe(target) {
     
     
    //非对象,直接返回
    if (typeof target !== 'object') {
     
     
        return target;
    }
    //将每个属性转换为getter和setter形式
    for (let key in target) {
     
     
        defineReactive(target, key, target[key])
    }
}
//模拟更新视图的方法
function updateView() {
     
     
    console.log("更新视图");
}

直接observeを呼び出してオブジェクトのプロパティの変化を検出する

既存の問題

  1. 業績不振
  2. オブジェクトに追加されたプロパティを検出できません
  3. 配列の長さプロパティの変更を検出できません

Vue インスタンスを作成するとき、Vue はデータ オプションのプロパティをトラバースし、Object.defineProperty を使用してプロパティにゲッターとセッターを追加し、データの読み取りをハイジャックします (ゲッターは依存関係を収集するために使用され、セッターは更新をディスパッチするために使用されます)。依存関係を内部的に追跡し、プロパティがアクセスされて変更されたときに変更を通知します。

各コンポーネント インスタンスには対応するウォッチャー インスタンスがあり、コンポーネントのレンダリング中にすべての依存データ属性 (依存コレクション、計算されたウォッチャー、ユーザー ウォッチャー インスタンス) を記録し、依存関係が変更されると、セッター メソッドはウォッチャーに通知します。このデータに依存するインスタンスが再計算される (更新をディスパッチする) ため、関連するコンポーネントが再レンダリングされます。

マウスのスクロール位置を記録する

App.vue第 1 レベルの route jump は破棄され、再構築されます. 第 1 レベルの route のキャッシュ コンポーネントをパッケージ化する必要があります. 2<keep-alive> のフック関数がトリガーされます.activated deactivated

コンポーネント内のナビゲーションでガード可能beforeRouteLeave

// 离开这个组件的路由导航守卫
  beforeRouteLeave (to, from, next) {
    
    
    // 跳走的时候获取组件的滚动位置
    this.top = this.$refs.article[this.active].$el.scrollTop
    next()
  },
  // 缓存组件激活触发的钩子函数
  activated () {
    
    
    if (this.$refs.article) {
    
    
      this.$refs.article[this.active].$el.scrollTop = this.top
    }
  }

ブラウザのイベントループ(JSの実行メカニズム)

ブラウザのイベント ループには、タスク キューの概念が含まれますすべての非同期タスクが実行された後、対応するコールバック関数がタスク キューに配置され順次処理のためにキューに入れられますタスクキューはマクロタスクキューマイクロタスクキューに分かれており、メインスレッドのコールスタックがクリアされたときにのみタスクキュー内のタスクが実行される、いわゆるJavaScriptの動作メカニズムです。


ブラウザ マクロ タスクには、主にsetTimeout()setInterval()が含まれます。
ブラウザーのマイクロタスクには、主にPromise.then()requestAnimationFrame() 、 process.nextTickが含まれます。

また、マイクロタスクはマクロタスクよりも優先度が高くなりますメイン スレッドのコール スタックがアイドル状態の場合、タスク キューに実行するタスクがあるかどうかを検出します.まず、マイクロタスク キューに実行するタスクがあるかどうかを確認します. ある場合は、マイクロタスク キューのタスクを実行します。マイクロタスク キューが空になると、マクロ タスク キュー内のタスクの実行が開始されます。マクロタスクがクリアされると、マイクロ タスク キュー内にタスクがあるかどうがチェックされます。イベントループ

最初のイベントループ

  • まずJSが同期か非同期かを判断し、同期でメインスレッドに入り、非同期でイベントテーブルに入る(ホスト環境)
  • 非同期タスクは関数をイベントテーブルに登録し、トリガー条件が成立するとイベントキュー(タスクキュー)にプッシュします。
  • 同期タスクがメイン スレッドに入ると、メイン スレッドがアイドル状態になるまで実行され、その後、実行可能な非同期タスクがあるかどうかをイベント キューに確認し、存在する場合はイベント キューにプッシュされます。メインスレッド

上記の 3 つのステップは、イベント ループであるループで実行されます。

2 番目のタイプのイベント ループ

 setTimeout(function(){
     
     
     console.log('A')
 });
 
 new Promise(function(resolve){
     
     
     console.log('B');
     for(var i = 0; i < 10000; i++){
     
     
         i == 99 && resolve();
     }
 }).then(function(){
     
     
     console.log('C')
 });
 
 console.log('D');

上記のコードの実行結果は次のとおりです。B D C A

実行シーケンスがこのようになっている理由を分析しますか?

これは、非同期タスクがマクロタスクとマイクロタスクに分かれているためです。

  • macro-task (マクロタスク): コード全体のスクリプト、setTimeout、setInterval を含む
  • micro-task (マイクロタスク): Promise.then, process.nextTick
  • この分類方法によると、JS の実行メカニズムは次のとおりです。
  • マクロタスクを実行し、途中でマイクロタスクに遭遇した場合、マイクロタスクの[イベントキュー]に入れる
  • 現在のマクロ タスクが実行された後、マイクロ タスクの [イベント キュー] をチェックし、その中のすべてのマイクロ タスクを順番に実行します。

上記の 2 つの手順を繰り返し、イベント ループ(1) イベント ループ(2) と組み合わせると、より正確になります。JS 実行メカニズム上。

具体的な実行プロセスは次のように分析されます。

首先执行script下的宏任务,遇到setTimeout,将其放到宏任务的【队列】里

遇到 new Promise直接执行,打印"B"

遇到then方法,是微任务,将其放到微任务的【队列里】

遇到同步任务console.log('D') 直接打印 "D"

本轮宏任务执行完毕,查看本轮的微任务,发现有一个then方法里的函数, 打印"C"

到此,本轮的event loop 全部完成。


下一轮的循环里,先执行一个宏任务,发现宏任务的【队列】里有一个 setTimeout里的函数,执行打印"A"

したがって、実行結果は次のようになります。B D C A

複雑な例を考えてみましょう:

console.log('1');
setTimeout(function() {
    
    
 
 
console.log('2');
process.nextTick(function() {
    
    
 
console.log('3');
 
 
})
new Promise(function(resolve) {
    
    
 
console.log('4');
resolve();
}).then(function() {
    
    
 
console.log('5')
})
})
//1 2 4 3 5 

実装プロセス:

1.マクロタスク同期コード console.log('1')

2. setTimeout、マクロ タスク イベント キューを追加、マイクロ タスクが見つからない、イベント ループの最初のラウンドが終了

3. 2 回目のイベント ループが開始され、最初にマクロ タスクが実行され、マクロ タスク Event Queue から setTimeout のコールバック関数が読み込まれます。

4. コード console.log('2') を同期し、process.nextTick を検索し、microtask イベント キューを追加します。

5. 新しい Promise、console.log('4') を同期的に実行、検索、microtask Event Queue を追加

6. マクロタスクが実行された後、次にマイクロタスクが実行され、最初に process.nextTick を実行し、次に Promise.then を実行します。

7. マイクロタスクの実行後、2 回目のイベント ループが完了し、マクロタスクが見つからず、イベント ループが終了します。

要約する

イベント ループは最初にマクロタスクを実行し、同期タスクがすぐに実行され、非同期タスクが対応するイベント キューにロードされ、マイクロタスクも対応するマイクロタスクのイベント キューにロードされます.すべての同期マイクロタスクが実行された後、マイクロタスクが見つかった場合 イベント キューに未完了のタスクがあり、それらを最初に実行すると、イベント ループのラウンドが完了したと見なされます。次に、マクロ タスクのキューに非同期コードがあるかどうかを確認し、ある場合は、イベント ループの 2 番目のラウンドを実行します。

SQL の基本構文

-- SELECT * FROM my_db_01.users;
-- 1.查询整个表所有的数据
-- select * from users
-- 2.查询具体的字段名字
-- select username,password from users
-- 3.查询id是1的这个字段 查询的条件写在where后面
-- select * from users where id=1
-- 4.查询users表里username这个字段 模糊查询 Z%表示以z开头的 %Z写在后面后面表示以z结尾的
-- select * from users where username like 'Z%'
-- 5.条件查询
-- select username,password from users where id>1 and status=0
-- 6.排序 desc(降序) asc(升序)
-- select * from users order by id desc
-- select * from users order by id asc
-- 7.添加
-- insert into users(username,password,status) values('zl',111,1)
-- 8.删除
-- delete from users where id=3
-- 9.修改(更新)update 表明 set 字段属性(多个字段用英文逗号隔开) where (修改的字段对应的id) 如果没有where 将修改整个表
-- update users set username='zs',password=555 where id=1
-- 10.函数count(*)
-- select count(*) from users where status=0

ウォッチ、メソッド、計算の違いは何ですか?

作用機序から:

  1. メソッド、ウォッチ、計算はすべて関数ベースですが、それぞれ異なります
  2. 監視と計算の両方が、Vue の依存関係追跡メカニズムに基づいています。はい、特定のデータが変更されると、このデータに依存するすべての「関連」データが「自動的に」変更されます。つまり、関連する関数を自動的に呼び出してデータの変更を実現します
  3. メソッドの場合: メソッドは、実行するために手動で呼び出す必要がある関数を定義するために使用されます。事前定義された関数を「自動的に実行」するウォッチおよび計算とは異なり、ウォッチ/計算と比較して、メソッドはデータ論理関係を処理せず、呼び出し可能な関数のみを提供します。

本来は:

  1. メソッドで定義された関数は、引き続き呼び出す必要があります。
  2. Computedは計算された属性です。実際には、データ オブジェクトのデータ属性と同じ型 (使用されている) です。
  3. **watch: **リスニング メカニズム + イベント メカニズムと同様

ウォッチとコンピューテッドの違い

  1. 機能的には、computed は計算された属性であり、watch は値の変化を監視し、対応するコールバックを実行します。
  2. キャッシュを呼び出すかどうか: 計算された関数が依存する属性は変更されていないため、現在の関数が呼び出されるとキャッシュから読み取られ、監視値が変更されるたびにウォッチがコールバックを実行します。
  3. return を呼び出すかどうか: 計算された関数はreturn を return に使用する必要があり、watch の関数は return を使用する必要はありません
  4. 監視が得意とするシナリオ: 1 つのデータが複数のデータに影響を与える-------検索ボックス。
  5. 計算が得意なシナリオ:1つのデータが複数のデータに影響される場合 – 利用シナリオ:値が複数の属性に影響される場合-------- ショッピングカートの商品決済

**watch: ** 属性監視

  1. ウォッチはデータの属性に依存するため、ウォッチの関数名はデータの属性名と一致している必要があります。データの属性が変更されると、ウォッチの関数が実行されます。
  2. watch の関数には 2 つのパラメーターがあり、前者は newVal、後者は oldVal です。
  3. watch の関数を呼び出す必要はありません。
  4. watch は、データの値が変化するかどうかのみを監視し、データのアドレスが変化するかどうかは監視しません。つまり、watch が参照型データの変化を監視したい場合は、詳細な監視を実行する必要があります。"obj.name"(){}------obj の属性が多すぎる場合、このメソッドの効率は非常に低くなります。obj:{handler(newVal){},deep:true}----- - 詳細な監視には、handler+deep メソッドを使用します。
  5. 特殊なケースでは、ウォッチは配列内の変更を監視できません. 特殊なケースでは、配列内のデータが変更されたときに、配列は変更されていますが、ビューは更新されていません. 配列を変更するには、splice() またはset を使用する必要があります。this .arr .splice ( 0 , 1 , 100 ) - - - - - arr の項目 0 から始まるデータを 100 に変更し、 this .set. this.arr.splice(0,1,100)-----arr の項目 0 から始まるデータを 100 に変更します。セット_ _ _ _ _ _ _ あらら_ _ スプライス( 0 , _ _ _ _ _1 1 0 0 )a r r項目0から始まる1データを1 0 0変更しますこれ.set ( this.arr , 0,100)--arr の項目0 のを 100 に変更します。
  6. immediate: true ページが最初にロードされたときにリスナーを実行します。
  7. 1 つのデータが複数のデータに影響する - アプリケーション シナリオ: 検索ボックス、フォーム入力、非同期更新、アニメーション
  8. 複雑なデータ型をリッスンしている場合は、詳細な監視を有効にする必要がありますdeep:true

計算: 計算されたプロパティ

  • キャッシュされた計算は依存関係に従って実行され、必要な場合にのみ更新されます。
  • 計算されたプロパティは、さまざまな複雑なロジックを完了し、最終的に結果を返すことができます; 計算されたプロパティは、複数の vue インスタンスのデータに依存することができます.データのいずれかが変更される限り、計算されたプロパティは再実行され、ビューは更新しました。これに加えて、計算されたプロパティは、他の計算されたプロパティおよび他のインスタンスからのデータに依存できます。
  • 1つのデータが複数のデータの影響を受ける - ショッピングカートの決済は、単価の数量と選択の有無によって影響されます

HTTP と HTTPS の違い (必須)

多くの人は常に http が https だと思っています。実はhttpとhttpsには大きな違いがあるので、httpsとhttpの違いを見てみましょう。

1: https と http とは何かについて話しましょう

httpsこれは、暗号化された伝送プロトコル チャネルを備えた、ハイパーテキスト セキュア伝送とも呼ばれる http のセキュア バージョンであり、SSL は、http 伝送に使用されるセキュアな暗号化基盤を提供します

http通常のハイパーテキスト転送プロトコルで、インターネット上ではすべてのファイルがこのHTTPプロトコルに従う必要があり、その機能はクライアントとサーバー間の相互要求を実現することです。

2: では、https と http の違いは何ですか違い

https と http の違い:

**1. **https のポートは 443、http のポートは 80 で、両者の接続方法は異なります.http の接続は非常にシンプルでステートレスです.HTTPS プロトコルは SSL+ によって構築されています. HTTP プロトコルであり、暗号化することができます 送信および身元認証のためのネットワーク プロトコル。

**2. **HTTP プロトコルは、データを暗号化せずにプレーン テキストでコンテンツを送信します. たとえば、ハッカーが Web ブラウザと Web サイト サーバー間の伝送メッセージを傍受した場合、その中のコンテンツを直接読み取ることができます。したがって、HTTP プロトコルは、銀行カード番号やパスワードなどの支払い情報など、一部の機密情報の送信には適していません。この HTTP プロトコルの欠点を解決するために、HTTPS は HTTP をベースに SSL プロトコルを追加し、ブラウザとサーバー間の通信を暗号化します。HTTPS プロトコルが安全である理由は、HTTPS プロトコルが送信データを暗号化するためであり、暗号化プロセスは非対称暗号化によって実現されます。

**3. ** HTTPS は証明書を申請するために CA に行く必要がありますが、http は必要ありません。

httpsとhttpの違いは何ですか

SSL証明書とは何ですか? (拡大)

HTTP プロトコルはコンテンツをクリア テキストで送信するため、HTTP プロトコルを使用して個人情報を送信するのは非常に安全ではありません. これらの個人データを確実に暗号化して送信できるようにするために、Netscape は、SSL プロトコルによって送信されるデータを暗号化するように設計しまし HTTP プロトコル、つまり HTTPS が誕生しました。ここで、S はセキュリティを表します。安全

SSL証明書はデジタル証明書の一種で、運転免許証の電子コピーに似ています。サーバー上で構成されるため、SSL サーバー証明書とも呼ばれます。効果ネットワーク トランザクション、データ転送、およびログインを保護するために使用されます。だからSSLは徐々に仕様になってきました(ECMAscriptがjs文法の仕様であるように)

nextTickの原理

Vue DOM の更新は非同期で実行されるため、つまり、データが変更されると、ビューはすぐには更新されませんが、データの変更を監視し、同じイベント ループでキャッシュします。ループが完了すると統合され、ビューが更新されます。更新された DOM を確実に取得するために、Vue.nextTick()メソッドは。

vue には nextTick という特別な API があります。公式ドキュメントによると、DOMが更新された後にコールバックを実行できます

MVVM フレームワークは DOM へのアクセスを推奨していませんが、特にサードパーティのプラグインを使用する場合は、DOM 操作が避けられない場合があります。そして nextTick は、更新された DOM を操作していることを確認するためのブリッジを提供します。

アプリケーション シナリオ:

  • Vue ライフサイクルの created() フック関数で実行される DOM 操作は、Vue.nextTick() のコールバック関数に配置する必要があります。
    • created()**理由:**フック関数の実行時に DOM が実際にはレンダリングされないためです。
  • データの変更後に実行される操作で、この操作がデータの変更に伴って変化する DOM 構造を使用する必要がある場合、この操作はコールバック関数に配置する必要がありますVue.nextTick()
    • 理由: Vue は DOM 更新を非同期に実行します. データの変更が監視される限り、Vue はキューを開き、同じイベント ループで発生するすべてのデータ変更をバッファします. 同じウォッチャーが複数回トリガーされた場合、それは一度行列。

要約する

以上が vue の nextTick メソッドの実装原理であり、まとめると以下のようになります。

  1. Vue は非同期キューを使用して DOM 更新を制御し、nextTick コールバックを連続して実行します
  2. 優先度の高い機能により、マイクロタスクはキュー内のマイクロタスクがイベントループの前に実行されることを保証できます
  3. 互換性の問題により、Vue はマイクロタスクからマクロタスクにダウングレードする必要がありました。

モジュールのドラッグ アンド ドロップの原理

ドラッグ アンド ドロップ機能は主に、ユーザーがドラッグ ソートドラッグ アンド ポップアップ ボックスの移動などのカスタム アクションを実行できるようにするために使用され、その効果は非常に優れています。ドラッグアンドドロップの原理について話しましょう。

1.プロセスアクションをドラッグ&ドロップ

①マウスダウン
②マウス移動
③マウスリリース

ここに知らせ: 移動イベントは、プレス イベント内に記述する必要があります。

2.ドラッグ&ドロップ処理で対応するJSイベント

①マウスが押されると、onmousedownイベントがトリガーされます

②マウスの動きでonmousemoveイベントが発生する

③マウスを離すとonmouseupイベントが発生する

3. 実現原理の説明

ドラッグアンドドロップは、実際にはマウスの移動距離を取得すること、つまり、移動前の位置の座標 (x, y) と移動中の位置の座標 (x, y) の差を計算することで実現されます。
マウスを押したり動かしたりすると、現在のマウス位置、つまり移動前の位置と移動中の位置を取得できます。

もう 1 つのポイントは、効果を得るには、ドラッグされた要素のスタイルを絶対位置または相対位置に設定する必要があることです。

要約:

①ページ内でのドラッグの原理:マウスを押して動かし、マウスを離す

トリガーイベントは、マウスを押すmousedown、マウスを動かす、mousemove マウスを離すmouseup

③ドラッグ&ドロップ処理:マウスの移動処理中に最新の値を取得してモーダルボックスの左と上の値に代入し、モーダルボックスがマウスに追従できるようにする

ページ上のマウスの座標からボックス内のマウスの座標を引いたものがモーダルボックスの実際の位置です。

⑤マウスが押されたら、ボックス内のマウスの座標を取得する必要があります。

⑥ マウスが移動したときのモーダルボックスの座標を、ページ上のマウスの座標からボックスの座標を引いたものに設定する. なお、移動イベントはプレスイベントに記述されている.

⑦マウスを離すとドラッグが止まる、つまりマウス移動イベントをキャンセルできる

コアコード

 		// 鼠标按下获取鼠标在盒子内的坐标
        obj.addEventListener('mousedown', function(e) {
     
     
          //获取鼠标在盒子中的坐标=鼠标在页面中的坐标减去盒子在页面中的坐标  
            var x = e.pageX - box.offsetLeft
            var y = e.pageY - box.offsetTop
                // 鼠标移动的时候,把鼠标在页面中的坐标,减去 鼠标在盒子内的坐标就是模态框的left和top值
                // 在全局页面中拖拽时要用document,如果用了obj,事件会来不及触发,导致鼠标脱离
            document.addEventListener('mousemove', move)
		function move(e) {
     
     
            box.style.left = e.pageX - x + 'px'
            box.style.top = e.pageY - y + 'px'
        }
        // 鼠标弹起,就让鼠标移动事件移除
        document.addEventListener('mouseup', function() {
     
     
            document.removeEventListener('mousemove', move)
        })

メモリーリーク

メモリリークとは

アプリケーションがメモリを占有する必要がなくなった場合、なんらかの理由で、オペレーティング システムまたは使用可能なメモリ プールによってメモリが解放されません。これをメモリ リークと呼びます。

メモリ リークを引き起こす可能性のある操作

1. グローバル変数が原因のメモリ リーク
2. クロージャが原因のメモリ リーク
3. 忘れられたタイマーまたはコールバック
4. dom が空または削除された場合、クリアされていないイベントが原因のメモリ リーク
5. 同じプロパティを繰り返し書き換えると A大量のメモリが占​​有されています (ただし、メモリは IE を閉じると解放されます)

6. setTimeout の最初のパラメーターが関数ではなく文字列を使用すると、メモリ リークが発生します。

JS メモリ リークの解決策

1. プログラムロジックに注意し、「デッドループ」などを避ける
2. 不要なグローバル変数やライフサイクルの長いオブジェクトを減らし、無駄なデータをタイムリーにガベージコレクションする 3.
オブジェクトを作りすぎないようにする 原則: no Things紛失したものは期限内に返却する必要があります

新しいオペレーターは正確に何をしますか?

1. 空のオブジェクトを作成する
2. this がこの新しいオブジェクトを指す
3. コンストラクターでコードを実行して、新しいオブジェクトにプロパティとメソッドを追加する
4. 新しいオブジェクトを返す: 戻り値を判断し、返されたオブジェクトを使用して、作成するオブジェクトがない場合

ヒープとスタックの違い

  • スタック領域 (stack): コンパイラによって自動的に確保および解放され、関数のパラメータ値、ローカル変数の値などが格納されます。その動作モードデータ構造のスタックに似ています。
  • ヒープ領域 (heap) : 一般的にプログラマーによって割り当てられ、解放されます. プログラマーが解放しない場合、プログラムの最後にオペレーティングシステムによって再利用される可能性があります.データ編成のヒープとは異なります、割り当て方法はリンクされたリストに似ています。

彼らの違い

1 応募方法

  • スタック:システムによって自動的に割り当てられますたとえば、関数のローカル変数 int b を宣言すると、システムはスタック内に b 用のスペースを自動的に作成します。
  • ヒープ:プログラマが自分で申請し、サイズを指定する必要がある Cではmalloc関数、C++ではnew演算子を使用

2 申請後のシステム対応

  • スタック:スタックの残りのスペースが要求されたスペースよりも大きい限りシステムはプログラムにメモリを提供します。それ以外の場合は、スタック オーバーフローを示す例外が報告されます。
  • ヒープ: The operating system has alinked list that records the memory address of the space . システムがプログラムからアプリケーションを受け取ると、リンク リストを走査して、要求されたスペースよりも大きいスペースを持つ最初のヒープ ノードを見つけます。次に、空きメモリ ノードのリンク リストからノードを削除し、このノードの領域をプログラムに割り当てます

要約:

(1) ヒープはヒープであり、スタックはスタックです。

(2) スタック領域はオペレーティング システムによって自動的に割り当て/解放され、ヒープ上の領域は手動で割り当て/解放されます。

(3) スタック空間は限られており、ヒープは大きな空きメモリ領域です。

(4) C の malloc 関数によって割り当てられたメモリ空間はヒープ上にあり、C++ の対応する new 演算子です。プログラムがコンパイルされると、変数と関数のメモリ割り当てがスタック上で実行され、メモリ操作中に関数が呼び出されたときにパラメーターがスタック上で渡されます。

堆和栈的概念存在于数据结构中和操作系统内存中。

在数据结构中,栈中数据的存取方式为先进后出。而堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大小来规定。完全二叉树是堆的一种实现方式。

在操作系统中,内存被分为栈区和堆区。

栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

堆区内存一般由程序员分配释放,若程序员不释放,程序结束时可能由垃圾回收机制回收。
复制代码

ファイルのアップロード方法

getData メソッドを使用して、サーバー側の切断に基づいて切断パラメータを取得します

console.log(this.cropper.getData())

純粋なクライアント側のトリミングでは、getCroppedCanvas を使用してトリミングされたファイル オブジェクトを取得します

  • 最初にインターフェースドキュメントを見てください

  • 看请求头:
    如果接口要求 Content-Type 是 application/json
    则传递普通 JavaScript 对象
    axios会自动转为json对象
    
    如果接口要求 Content-Type 是 multipart/form-data
    则你必须传递 FormData 对象
    
    const formData = new FormData()
            formData.append('photo', blob)
    
    // 点击完成时间
    onConfirm () {
    
    
      // 基于服务端的裁切使用 getData 方法获取裁切参数
      // console.log(this.cropper.getData())

      // 纯客户端的裁切使用 getCroppedCanvas 获取裁切的文件对象
      this.cropper.getCroppedCanvas().toBlob(async blob => {
    
    
        // console.log(blob) // 裁剪后的结果信息
        // 弹出loading页面
        this.$toast.loading({
    
    
          message: '保存中...',
          forbidClick: true, // 禁止背景点击
          duration: 0 // 持续展示
        })
        try {
    
    
          // 1.创建formData对象
          const obj = new FormData()
          // 2.给对象obj添加key和value
          obj.append('photo', blob)
          // 3.发请求
          const {
    
     data } = await updateUserPhoto(obj)
          // 4.更新父组件对象
          this.$emit('update:photo', data.data.photo)
          // 5.关闭弹层
          this.$emit('update:close', false)
          this.$toast.success('修改成功')
        } catch (error) {
    
    
          this.$toast.fail('修改失败')
        }
      })
    }

BFCとは

ブロック フォーマット コンテキスト (BFC) は、Web ページのビジュアル CSS レンダリングの一部であり、ブロック レベル ボックスのレイアウト プロセスが発生する領域であり、フローティング要素が他の要素と相互作用する場所です。

次のメソッドは、ブロック フォーマット コンテキストを作成します。

  • ルート要素 ( <html>)
  • 浮動要素 (float値はありませんnone)
  • 絶対配置要素 (position値はabsoluteまたはfixed)
  • インラインブロック要素 (displayinline-block)
  • table_cell ( displayvalue table-cell、HTML テーブル セルのデフォルト)
  • table_title (displaytable-caption、HTML table_title デフォルト)
  • 匿名のテーブル セル要素 (display値はtable, table-row, table-row-group,です(HTML テーブルのデフォルトはそれぞれ tr, tbody, thead, tfoot )table-header-groupまたは)table-footer-groupinline-table
  • overflowvisible以外の値を持つclipブロック要素
  • displayflow-rootを持つ要素
  • containlayoutまたはの値を持つ要素contentpaint
  • flex 要素 (display値はflexor)、それ自体がflexgrid 、またはtableコンテナーinline-flexでない場合
  • Grid 要素 (displaygridinline-gridor 要素の直接の子)、それ自体がflexgrid、またはtableコンテナーでない場合
  • 複数列コンテナ (column-countまたはcolumn-width(en-US)の値以外、 for をauto含む)column-count1
  • column-span要素が複数列コンテナにラップされていなくても、値allが要素は常に新しい BFC を作成します (仕様変更Chrome バグ)。

書式設定コンテキストはレイアウトに影響します。通常、フロートの配置とクリアのために新しい BFC を作成します、レイアウトを変更する代わりに、次のようになるためです。

  • インナーフロート入り
  • 外部フロートを除外
  • マージンが重ならないようにします(ブロックのmargin-topmargin-bottom は、サイズが 1 つのマージンの最大値 (または、それらが等しい場合は、そのうちの 1 つだけ) である 1 つのマージンにマージ (折りたたまれる) されることがあります)。この動作は次のとおりです。マージン崩壊と呼ばれます。)

マージンが重なる状況は 3 つあります。

  1. 隣接する 2 つの要素間のマージンは、後者の要素がclear-fix でクリアされない限り重なります。
  2. 親要素と子孫要素を分離するコンテンツがないと、親ブロック要素とその子孫ブロック要素の外側の境界がオーバーラップし、オーバーラップは最終的に親ブロック要素の外側にオーバーフローします。
  3. 空のブロック レベル要素:境界線の崩壊は、ブロック要素の上境界線がmargin-top要素の下境界線に直接接着されている場合にも発生します。margin-bottomこれは、ブロック要素に境界線がまったく設定されていない場合に発生しますborder、パディングpadding、高さheight、最小高さmin-height、最大高さmax-height、コンテンツがインラインに設定されている場合、またはclear-fixが追加されている場合。

==注:== float floatと position=absolute絶対配置の要素は、マージンオーバーラップ動作を生成しません。

js遅延読み込みの方法は何ですか?

js の読み込み、解析、実行はページのレンダリング プロセスをブロックするため、ページのレンダリング速度を向上させるために、js スクリプトをできるだけ遅延して読み込むことができることを願っています。私が学んだいくつかの方法は次のとおりです。

最初の方法は、通常、ドキュメントの一番下に js スクリプトを配置します。、できるだけ最後に js スクリプトをロードして実行するようにします。

2番目の方法は、jsスクリプトに追加することです延期属性、この属性により、スクリプトを同期的にロードして解析できるようになり、ドキュメントが解析された後にスクリプトファイルが実行されるため、ページのレンダリングがブロックされません。defer 属性が設定された複数のスクリプトは、指定により順次実行されますが、一部のブラウザではそうでない場合があります。

3 つ目の方法は、js スクリプトに追加することです。非同期属性, この属性は、スクリプトを非同期的にロードし、ページの解析プロセスをブロックしませんが、スクリプトがロードされた直後に js スクリプトを実行します. このとき、ドキュメントが解析されない場合は、それもブロックされます. 複数の非同期属性を持つスクリプトの実行順序は予測できず、通常、コードの順序で順次実行されることはありません

4つ目の方法はDOM タグを動的に作成するこのようにして、ドキュメントの読み込みイベントを監視し、スクリプト タグを動的に作成して、ドキュメントが読み込まれたときに js スクリプトをインポートできます。

Ajax とは? Ajax の作成方法

私の理解では、ajax は、js スクリプトからサーバーへの http 通信を直接開始し、ページ全体を更新することなく、サーバーから返されたデータに従って Web ページの対応する部分を更新することによる、非同期通信の方法であるということです。ajax を作成するには、いくつかの手順があります。

1 つ目は、XMLHttpRequest オブジェクトを作成することです。

次に、このオブジェクトで open メソッドを使用して http リクエストを作成します。open メソッドで必要なパラメータは、リクエストのメソッド、リクエストのアドレス、非同期かどうか、およびユーザーの認証情報ですリクエストを行う前に、このオブジェクトにいくつかの情報とリスナー関数を追加できます。たとえば、setRequestHeader メソッドを使用してヘッダー情報をリクエストに追加できます。このオブジェクトにステータスリスナー関数を追加することもできます。XMLHttpRequest オブジェクトには合計 5 つの状態があります. 状態が変化すると onreadystatechange イベントが発生します. 成功したリクエストの結果を処理するようにリスナー関数を設定できます. オブジェクトの readyState が 4 に変わると、サーバーから返されたデータが受信されたことを意味します. この時点で、リクエストのステータスを判断できます. ステータスが 2xx または 304 の場合は、正常に返されたことを意味します. . この時点で、応答のデータを使用してページを更新できます。オブジェクトとリスナー関数のプロパティが設定されている場合

最後に、sent メソッドを呼び出してサーバーへのリクエストを開始し、パラメーターを送信データ本体として渡すことができます。xhr.send(null);

let xhr = new XMLHttpRequest();

// 创建 Http 请求
xhr.open("GET", SERVER_URL, true);

// 设置状态监听函数
xhr.onreadystatechange = function() {
     
     
  if (this.readyState !== 4) return;

  // 当请求成功时
  if (this.status === 200) {
     
     
    handle(this.response);
  } else {
     
     
    console.error(this.statusText);
  }
};

// 设置请求失败时的监听函数
xhr.onerror = function() {
     
     
  console.error(this.statusText);
};

// 设置请求头信息
xhr.responseType = "json";
xhr.setRequestHeader("Accept", "application/json");

// 发送 Http 请求
xhr.send(null);

アンチシェイクとスロットリングとは何ですか?

導入

JavaScript では、アンチシェイクとスロットリングは実際には非常に重要な概念です。主なアプリケーション シナリオは、スクロールの監視やいいね機能など、頻繁にトリガーされるイベントです.一度気に入ったデータをバックグラウンドに送信することは不可能です.このとき、手ブレ防止とスロットリングが必要です.

アンチシェイクとスロットリングの核心はタイマーです. タイマーの概念を知る必要があります. タイマーの概念を知る必要があります. タイマーは, タイミングの後でトリガーされる前にタイマーをクリアします. このタイマーメソッドはトリガーされません.

手ぶれ補正機能の機能は、機能の実行時間を一定時間内に制御することです。アンチバウンスとは、関数が N 秒以内に 1 回 (前回) だけ実行され、N 秒以内に再度トリガーされた場合、遅延時間が再計算されることを意味します。

スロットリング関数の役割は単位時間を指定することであり、関数の実行はこの単位時間内に最大で 1 回のみトリガーできます。関数がこの単位時間内に複数回トリガーされた場合、1 回のみ有効になります。

lodashvue では、_debounce のいずれかを使用できます

最初のパラメーターは関数で、2 番目のパラメーターは遅延時間であることに注意してください。

事前解析

1. 私たちの js エンジンは js を 2 つのステップで実行します:コード実行の事前解析

(1). 事前解析 js エンジンは、allvar およびfunction現在のスコープの先頭に昇格させます。

(2). コードの実行は、コードが書かれた順序で上から下に実行されます。

2. 事前解析は、変数事前解析 (変数昇格) と関数事前解析 (関数昇格) に分けられます。

(1) 変数の昇格とは、代入操作を昇格させずに、

(2) 関数昇格とは、関数を呼び出さずに、すべての関数宣言を現在のスコープの先頭に昇格させることです。

  • 知らせ
    • グローバル変数はローカル変数にアクセスできません
    • 関数内に var キーワードを追加することはローカルであり、仮パラメーターもローカルです (内部に var を追加しない変数の割り当てもグローバル変数です)。
    • var キーワードがない場合、またはパラメーターが渡されない場合、a=1 はグローバルです

試作チェーン

  • __proto__プロトタイプがプロトタイプ オブジェクトを指している限り、しかしObject.prototype.__proto__ それは空(null)を指しています

各インスタンス オブジェクトには、コンストラクターのプロトタイプ オブジェクトを指す __proto__ 属性があり、コンストラクターのプロトタイプ オブジェクトもオブジェクトであり、__proto__ 属性も持っているため、レイヤーごとに形成されます。試作チェーン

コンストラクター インスタンスとプロトタイプ オブジェクトの三角形

1. コンストラクターのプロトタイプ属性はコンストラクターのプロトタイプ オブジェクトを指します
2. インスタンス オブジェクトはコンストラクターによって作成され、インスタンス オブジェクトの __proto__ 属性はコンストラクターのプロトタイプ オブジェクトを指します
3. のコンストラクター属性コンストラクターのプロトタイプ オブジェクトはコンストラクターを指し、インスタンス オブジェクトのプロトタイプのコンストラクター属性もコンストラクターを指します。

プロトタイプ チェーンとメンバー ルックアップ メカニズム

__proto__オブジェクト プロトタイプの重要性は、オブジェクト メンバー検索メカニズムの方向またはルートを提供することです。

どのオブジェクトにもプロトタイプ オブジェクト、つまりプロトタイプ属性があります. すべてのプロトタイプ オブジェクトもオブジェクトであり、オブジェクトは __proto__ 属性を持っています. このように、レイヤーごとに検索すると、チェーンが形成され、これをプロトタイプと呼びます.鎖;

当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。
如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)。
如果还没有就查找原型对象的原型(Object的原型对象)。
依此类推一直找到 Object 为止(null)。


查找原则:
	实例对象访问属性:
		先去本身构造函数上去查找,如果本身没有要查找的属性或者方法,会自动去原型对象去查找
		如果原型对象也没有,再去原型对象的原型对象去查找。
		如果都没有返回undefined。 如果找到了停止查找
设置原则:
	给实例对象设置一个属性,本质上是给实例添加属性,并不会修改原型的内容。

おすすめ

転載: blog.csdn.net/qq_43375584/article/details/125565184