Практические основные функции инструментов в исходном коде Vue3, понятные новичкам.

внешний интерфейс JavaScript Vue.js
Практические основные функции инструментов в исходном коде Vue3, понятные новичкам.

1. Введение

Привет всем, яВакагава. Добро пожаловать, чтобы следовать за мнойПубличный аккаунт Wakagawa Vision, недавно организованныйЧтение исходного кода, если вам интересно, вы можете добавить меня в WeChatruochuan12, долгосрочный обмен и обучение.

написано раньше"Изучение серии "Общая архитектура исходного кода""ВключатьjQuery,underscore,lodash,vuex,sentry,axios,redux,koa,vue-devtools,vuex4Десять статей с исходным кодом.

Написание относительно сложного исходного кода стоило мне времени и энергии, и я не получил много лайков от чтения.На самом деле, это был настоящий удар. С точки зрения объема чтения и выгоды для читателей это не может способствовать непрерывному выпуску статей авторами.

Так что измените свое мнение и напишите несколько относительно простых для понимания статей.На самом деле исходный код не так сложен, как можно себе представить, по крайней мере, его нужно понять. такие как функции полезности. Эта статья через обучениеVue3Исходный код функционального модуля инструмента в исходном коде, изучите исходный код для собственного использования. Гёте однажды сказал: «Читать хорошую книгу — значит разговаривать с благородными людьми». То же самое можно получить: чтение исходного кода — это тоже способ обучения и общения с автором.

Прочитав эту статью, вы узнаете:

1. 如何学习 JavaScript 基础知识,会推荐很多学习资料
2. 如何学习调试 vue 3 源码
3. 如何学习源码中优秀代码和思想,投入到自己的项目中
4. Vue 3 源码 shared 模块中的几十个实用工具函数
5. 我的一些经验分享

sharedмодуль57个Инструментальная функция, на этот раз я прочитал одну из них30余个.

2. Подготовка окружающей среды

2.1 Прочтите Руководство по участию в проектах с открытым исходным кодом

Открытьvue-next, Проекты с открытым исходным кодом в целом могутREADME.mdили.github/contributing.mdНайдите рекомендации по содействию.

И Contribution Guide много пишет об участии в разработке проекта. Например, как запустить, какова структура каталогов проекта. Как инвестировать в развитие, какие нужны резервы знаний и т.д.

мы можемСтруктура каталогов проектаописание, найденоsharedмодуль.

shared: Internal utilities shared across multiple packages (especially environment-agnostic utils used by both runtime and compiler packages).

README.mdа такжеcontributing.mdОбычно на английском языке. Некоторые люди могут быть поставлены в тупик. На самом деле, если вы этого не понимаете, вы можете использовать инструменты перевода, такие как перевод с разметкой слов, полностраничный перевод и перевод Baidu. Затем добавьте английский язык в план последующего обучения.

Эта статья оsharedмодуль, соответствующий путь к файлу:vue-next/packages/shared/src/index.ts

также можно использоватьgithub1sдоступ, быстрее.github1s packages/shared/src/index.ts

2.2 Следуйте руководству по проекту, чтобы упаковать и собрать код

Чтобы уменьшить сложность статьи, я упаковал ее в соответствии с методом, описанным в руководстве по вкладу.tsпревратился вjs. Если вам нужно упаковать, вы также можете обратиться к сборке пакета ниже.

вам нужно убедитьсяNode.jsверсия10+, а такжеyarnВерсия1.x Yarn 1.x.

вы установилиNode.jsверсия скорее всего ниже10. Самый простой способ — зайти на официальный сайт для переустановки. также можно использоватьnvmи т.д. управлениеNode.jsВерсия.

node -v
# v14.16.0
# 全局安装 yarn

# 推荐克隆我的项目
git clone https://github.com/lxchuan12/vue-next-analysis.git
cd vue-next-analysis/vue-next

# 或者克隆官方项目
git clone https://github.com/vuejs/vue-next.git
cd vue-next

npm install --global yarn
yarn # install the dependencies of the project
yarn build

может получитьvue-next/packages/shared/dist/shared.esm-bundler.jsфайл просто простоjsдокумент. Далее следует объяснение некоторых из этих методов.

Конечно, передняя часть может быть более подробной. я могу говорить прямо3. 工具函数. Но благодаря моему представлению выше даже новички могут понять исходный код некоторых проектов с открытым исходным кодом, и, возможно, у них будет определенное чувство выполненного долга. Кроме того, когда на собеседовании задаются аналогичные вопросы или письменные контрольные вопросы, вы говоритеVue3Если вы узнаете из исходного кода, интервьюер обязательно посмотрит на вас с восхищением.

2.3 Как создать исходную карту для отладки исходного кода vue-next

Знакомые со мной читатели знают, что я часто подчеркиваю созданиеsourcemapПосмотрите на отладку исходного кода, так как настроить генерациюsourcemap, как отлаживать. Эту часть можно просто пропустить, а потом внимательно посмотреть на практическую работу.

фактическиРуководство по взносамописан в.

Build with Source Maps Use the --sourcemap or -s flag to build with source maps. Note this will make the build much slower.

так вvue-next/package.jsonдобавить"dev:sourcemap": "node scripts/dev.js --sourcemap",yarn dev:sourcemapвыполнить для генерацииsourcemap, или напрямуюbuild.

// package.json
{
    "version": "3.2.1",
    "scripts": {
        "dev:sourcemap": "node scripts/dev.js --sourcemap"
    }
}

выведет что-то вродеvue-next/packages/vue/src/index.ts → packages/vue/dist/vue.global.jsИнформация.

вpackages/vue/dist/vue.global.js.mapто естьsourcemapфайл.

Давайте найдем пример на официальном сайте Vue3, вvue-next/examples/index.html. его содержаниеpackages/vue/dist/vue.global.js.

// vue-next/examples/index.html
<script src="../../packages/vue/dist/vue.global.js"></script>
<script>
    const Counter = {
        data() {
            return {
                counter: 0
            }
        }
    }

    Vue.createApp(Counter).mount('#counter')
</script>

Затем мы создаем новое окно терминала,yarn serve, открыть в браузереhttp://localhost:5000/examples/, как показано на рисунке ниже, нажмитеF11После входа в функцию вы можете с радостью отлаживать исходный код.

vue-next-debugger

3. Вспомогательные функции

Эта статья в основном следует исходному кодуvue-next/packages/shared/src/index.tsзаказ писать. Также сохраняет некоторые методы импорта извне.

Мы также можем пройтиtsфайл, чтобы увидеть, где используется функция. в то же времяVSCodeДля запуска и отладки кода JS мы рекомендуем код, написанный г-ном Ханом.code runnerплагин.

3.1 BabelParserDefaultPlugins Babel анализирует плагин по умолчанию

/**
 * List of @babel/parser plugins that are used for template expression
 * transforms and SFC script transforms. By default we enable proposals slated
 * for ES2020. This will need to be updated as the spec moves forward.
 * Full list at https://babeljs.io/docs/en/next/babel-parser#plugins
 */
const babelParserDefaultPlugins = [
    'bigInt',
    'optionalChaining',
    'nullishCoalescingOperator'
];

Вот несколько стандартных плагинов. Интересно увидеть английскую аннотацию для просмотра.

3.2 EMPTY_OBJ Пустой объект

const EMPTY_OBJ = (process.env.NODE_ENV !== 'production')
    ? Object.freeze({})
    : {};

// 例子:
// Object.freeze 是 冻结对象
// 冻结的对象最外层无法修改。
const EMPTY_OBJ_1 = Object.freeze({});
EMPTY_OBJ_1.name = '若川';
console.log(EMPTY_OBJ_1.name); // undefined

const EMPTY_OBJ_2 = Object.freeze({ props: { mp: '若川视野' } });
EMPTY_OBJ_2.props.name = '若川';
EMPTY_OBJ_2.props2 = 'props2';
console.log(EMPTY_OBJ_2.props.name); // '若川'
console.log(EMPTY_OBJ_2.props2); // undefined
console.log(EMPTY_OBJ_2);
/**
 * 
 * { 
 *  props: {
     mp: "若川视野",
     name: "若川"
    }
 * }
 * */

process.env.NODE_ENVдаnodeПеременная среды в проекте, обычно определяемая как:developmentа такжеproduction. Пишите код в соответствии с окружением. Например, в среде разработки есть такая информация, как отчеты об ошибках, но в производственной среде эти предупреждения об ошибках не нужны.

3.3 Пустой массив EMPTY_ARR

const EMPTY_ARR = (process.env.NODE_ENV !== 'production') ? Object.freeze([]) : [];

// 例子:
EMPTY_ARR.push(1) // 报错,也就是为啥生产环境还是用 []
EMPTY_ARR.length = 3;
console.log(EMPTY_ARR.length); // 0

3.4 Пустая функция NOOP

const NOOP = () => { };

// 很多库的源码中都有这样的定义函数,比如 jQuery、underscore、lodash 等
// 使用场景:1. 方便判断, 2. 方便压缩
// 1. 比如:
const instance = {
    render: NOOP
};

// 条件
const dev = true;
if(dev){
    instance.render = function(){
        console.log('render');
    }
}

// 可以用作判断。
if(instance.render === NOOP){
 console.log('i');
}
// 2. 再比如:
// 方便压缩代码
// 如果是 function(){} ,不方便压缩代码

3.5 НЕТ функций, которые всегда возвращают false

/**
 * Always return false.
 */
const NO = () => false;

// 除了压缩代码的好处外。
// 一直返回 false

3.6 isOn Определяет, начинается ли строка с on и первая ли буква после on не является строчной.

const onRE = /^on[^a-z]/;
const isOn = (key) => onRE.test(key);

// 例子:
isOn('onChange'); // true
isOn('onchange'); // false
isOn('on3change'); // true

onREрегулярно.^Символ в начале указывает, что такое начало. А в другом месте значит нет.

Напротив:$Матч в конце, а это значит, что конец.

[^a-z]значит нетaприбытьzстрочные буквы.

Также порекомендуйте обычный онлайн-инструмент.

regex101

Кроме того, достаточно прочитать мини-книгу Лао Яо.

Отправь его: "JavaScript Регулярное выражение мини-книги" Выходи "!

3.7 прослушиватель isModelListener

Определить, начинается ли строка сonUpdate:начало

const isModelListener = (key) => key.startsWith('onUpdate:');

// 例子:
isModelListener('onUpdate:change'); // true
isModelListener('1onUpdate:change'); // false
// startsWith 是 ES6 提供的方法

Руководство по началу работы с ES6: новые методы для строк

Многие методы упоминаются во «Вводном руководстве по ES6», поэтому я не буду вдаваться в подробности.

3.8 расширить слияние наследования

Возможно, правильнее было бы сказать «слияние».

const extend = Object.assign;

// 例子:
const data = { name: '若川' };
const data2 = extend(data, { mp: '若川视野', name: '是若川啊' });
console.log(data); // { name: "是若川啊", mp: "若川视野" }
console.log(data2); // { name: "是若川啊", mp: "若川视野" }
console.log(data === data2); // true

3.9 удалить: удаляет элемент из массива.

const remove = (arr, el) => {
    const i = arr.indexOf(el);
    if (i > -1) {
        arr.splice(i, 1);
    }
};

// 例子:
const arr = [1, 2, 3];
remove(arr, 3);
console.log(arr); // [1, 2]

spliceНа самом деле, это очень ресурсоемкий метод. Чтобы удалить элемент в массиве, все остальные элементы должны быть перемещены.

расширение:axios InterceptorManagerИсходный код перехватчика, перехватчики хранятся в массиве. Но при фактическом удалении перехватчика просто установите перехватчик наnull. Скорее, чемspliceУдалить. Последнее исполнениеnullне реализует, тот же эффект.axiosСледует сказать, что в сценарии с перехватчиком большое внимание уделялось производительности.

Смотри нижеaxiosПример кода перехватчика:

// 代码有删减
// 声明
this.handlers = [];

// 移除
if (this.handlers[id]) {
    this.handlers[id] = null;
}

// 执行
if (h !== null) {
    fn(h);
}

3.10 Является ли hasOwn собственностью самой себя?

const hasOwnProperty = Object.prototype.hasOwnProperty;
const hasOwn = (val, key) => hasOwnProperty.call(val, key);

// 例子:

// 特别提醒:__proto__ 是浏览器实现的原型写法,后面还会用到
// 现在已经有提供好几个原型相关的API
// Object.getPrototypeOf
// Object.setPrototypeOf
// Object.isPrototypeOf

// .call 则是函数里 this 显示指定以为第一个参数,并执行函数。

hasOwn({__proto__: { a: 1 }}, 'a') // false
hasOwn({ a: undefined }, 'a') // true
hasOwn({}, 'a') // false
hasOwn({}, 'hasOwnProperty') // false
hasOwn({}, 'toString') // false
// 是自己的本身拥有的属性,不是通过原型链向上查找的。

Object API может видеть статью, которую я написал раньшеВесь API-анализ объектов JavaScript, написано довольно развернуто.

3.11 Оценка массива isArray

const isArray = Array.isArray;

isArray([]); // true
const fakeArr = { __proto__: Array.prototype, length: 0 };
isArray(fakeArr); // false
fakeArr instanceof Array; // true
// 所以 instanceof 这种情况 不准确

3.12 isMap определяет, является ли он объектом Map

const isMap = (val) => toTypeString(val) === '[object Map]';

// 例子:
const map = new Map();
const o = { p: 'Hello World' };

map.set(o, 'content');
map.get(o); // 'content'
isMap(map); // true

ES6 предоставляет структуру данных карты. Он подобен объекту и также представляет собой набор пар ключ-значение, но область действия «ключей» не ограничивается строками, и в качестве ключей могут использоваться различные типы значений (включая объекты). Другими словами, структура Object обеспечивает соответствие "строка-значение", а структура Map обеспечивает соответствие "значение-значение", что является более полной реализацией структуры Hash. Если вам нужна структура данных "ключ-значение", Map больше подходит, чем Object.

3.13 isSet определяет, является ли он объектом Set

const isSet = (val) => toTypeString(val) === '[object Set]';

// 例子:
const set = new Set();
isSet(set); // true

ES6Предоставляет новые структуры данныхSet. Он похож на массив, но все значения членов уникальны и нет повторяющихся значений.

Setсам по себе является конструктором, используемым для генерацииSetструктура данных.

3.14 isDate определяет, является ли объект Date

const isDate = (val) => val instanceof Date;

// 例子:
isDate(new Date()); // true

// `instanceof` 操作符左边是右边的实例。但不是很准,但一般够用了。原理是根据原型链向上查找的。

isDate({__proto__: new Date()}); // true
// 实际上是应该是 Object 才对。
// 所以用 instanceof 判断数组也不准确。
// 再比如
({__proto__: [] }) instanceof Array; // true
// 实际上是对象。
// 所以用 数组本身提供的方法 Array.isArray 是比较准确的。

3.15 isFunction определяет, является ли это функцией.

const isFunction = (val) => typeof val === 'function';
// 判断函数有多种方法,但这个是比较常用也相对兼容性好的。

3.16 isString определяет, является ли это строкой

const isString = (val) => typeof val === 'string';

// 例子:
isString('') // true

3.17 isSymbol определяет, является ли он символом

const isSymbol = (val) => typeof val === 'symbol';

// 例子:
let s = Symbol();

typeof s;
// "symbol"
// Symbol 是函数,不需要用 new 调用。

ES6Введен новый примитивный тип данныхSymbol, представляющий уникальное значение.

3.18 isObject оценивает, является ли он объектом

const isObject = (val) => val !== null && typeof val === 'object';

// 例子:
isObject(null); // false
isObject({name: '若川'}); // true
// 判断不为 null 的原因是 typeof null 其实 是 object

3.19 isPromise определяет, является ли это обещанием

const isPromise = (val) => {
    return isObject(val) && isFunction(val.then) && isFunction(val.catch);
};

// 判断是不是Promise对象
const p1 = new Promise(function(resolve, reject){
  resolve('若川');
});
isPromise(p1); // true

// promise 对于初学者来说可能比较难理解。但是重点内容,JS异步编程,要着重掌握。
// 现在 web 开发 Promise 和 async await 等非常常用。

Рекомендованные книги вы можете прочитать в конце статьиPromiseОсвойте соответствующие главы. Также рекомендую эту мини-книгуМини-книга обещаний JavaScript (китайская версия)

3.20 объект objectToString в строку

const objectToString = Object.prototype.toString;

// 对象转字符串

3.21 объект toTypeString в строку

const toTypeString = (value) => objectToString.call(value);

// call 是一个函数,第一个参数是 执行函数里面 this 指向。
// 通过这个能获得 类似  "[object String]" 其中 String 是根据类型变化的

3.22 объект toRawType для строки Перехват нескольких последних цифр

const toRawType = (value) => {
    // extract "RawType" from strings like "[object RawType]"
    return toTypeString(value).slice(8, -1);
};

// 截取到
toRawType('');  'String'

может быть перехваченString Arrayи т.д. эти типы

даJSОчень важная точка знаний для оценки типов данных.

JSЕсть еще typeof для определения типа, но он не очень точен, да и определить можно не так много.

Это основы

mdn typeof документация, документация более подробная, а также реализована очень полнаяtypeфункция, в этой статье мы не будем вдаваться в подробности.

// typeof 返回值目前有以下8种 
'undefined'
'object'
'boolean'
'number'
'bigint'
'string'
'symobl'
'function'

3.23 isPlainObject оценивает, является ли он чистым объектом.

const objectToString = Object.prototype.toString;
const toTypeString = (value) => objectToString.call(value);
// 
const isPlainObject = (val) => toTypeString(val) === '[object Object]';

// 前文中 有 isObject 判断是不是对象了。
// isPlainObject 这个函数在很多源码里都有,比如 jQuery 源码和 lodash 源码等,具体实现不一样
// 上文的 isObject([]) 也是 true ,因为 type [] 为 'object'
// 而 isPlainObject([]) 则是false
const Ctor = function(){
    this.name = '我是构造函数';
}
isPlainObject({}); // true
isPlainObject(new Ctor()); // true

3.24 isIntegerKey Определяет, является ли значение ключа числовой строкой.

const isIntegerKey = (key) => isString(key) &&
    key !== 'NaN' &&
    key[0] !== '-' &&
    '' + parseInt(key, 10) === key;

// 例子:
isIntegerKey('a'); // false
isIntegerKey('0'); // true
isIntegerKey('011'); // false
isIntegerKey('11'); // true
// 其中 parseInt 第二个参数是进制。
// 字符串能用数组取值的形式取值。
//  还有一个 charAt 函数,但不常用 
'abc'.charAt(0) // 'a'
// charAt 与数组形式不同的是 取不到值会返回空字符串'',数组形式取值取不到则是 undefined

3.25 makeMap && isReservedProp

Передайте строку, разделенную запятыми, чтобы сгенерироватьmap(пара ключ-значение) и возвращает функцию для обнаруженияkeyЯвляется ли ценность в этомmapсередина. Второй параметр — это опция нижнего регистра.

/**
 * Make a map and return a function for checking if a key
 * is in that map.
 * IMPORTANT: all calls of this function must be prefixed with
 * \/\*#\_\_PURE\_\_\*\/
 * So that rollup can tree-shake them if necessary.
 */
function makeMap(str, expectsLowerCase) {
    const map = Object.create(null);
    const list = str.split(',');
    for (let i = 0; i < list.length; i++) {
        map[list[i]] = true;
    }
    return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val];
}
const isReservedProp = /*#__PURE__*/ makeMap(
// the leading comma is intentional so empty string "" is also included
',key,ref,' +
    'onVnodeBeforeMount,onVnodeMounted,' +
    'onVnodeBeforeUpdate,onVnodeUpdated,' +
    'onVnodeBeforeUnmount,onVnodeUnmounted');

// 保留的属性
isReservedProp('key'); // true
isReservedProp('ref'); // true
isReservedProp('onVnodeBeforeMount'); // true
isReservedProp('onVnodeMounted'); // true
isReservedProp('onVnodeBeforeUpdate'); // true
isReservedProp('onVnodeUpdated'); // true
isReservedProp('onVnodeBeforeUnmount'); // true
isReservedProp('onVnodeUnmounted'); // true

3.26 cacheStringFunction кэш

const cacheStringFunction = (fn) => {
    const cache = Object.create(null);
    return ((str) => {
        const hit = cache[str];
        return hit || (cache[str] = fn(str));
    });
};

Эта функция также похожа на описанную выше функцию MakeMap. Это просто функция, которая принимает параметры. Одноэлементный шаблон JS в главе 4 книги "JavaScript Design Patterns and Development Practice" также является аналогичной реализацией.

var getSingle = function(fn){ // 获取单例
    var result;
    return function(){
        return result || (result = fn.apply(this, arguments));
    }
};

Ниже приведены некоторые закономерности, которые система рекомендует для изучения закономерностей.Отправьте ему: «Вышла мини-книга по регулярным выражениям JavaScript»!, все сказали хорошо. Поэтому в этой статье не будет слишком много знаний о регуляризации.

// \w 是 0-9a-zA-Z_ 数字 大小写字母和下划线组成
// () 小括号是 分组捕获
const camelizeRE = /-(\w)/g;
/**
 * @private
 */
// 连字符 - 转驼峰  on-click => onClick
const camelize = cacheStringFunction((str) => {
    return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''));
});
// \B 是指 非 \b 单词边界。
const hyphenateRE = /\B([A-Z])/g;
/**
 * @private
 */

const hyphenate = cacheStringFunction((str) => str.replace(hyphenateRE, '-$1').toLowerCase());

// 举例:onClick => on-click
const hyphenateResult = hyphenate('onClick');
console.log('hyphenateResult', hyphenateResult); // 'on-click'

/**
 * @private
 */
// 首字母转大写
const capitalize = cacheStringFunction((str) => str.charAt(0).toUpperCase() + str.slice(1));
/**
 * @private
 */
// click => onClick
const toHandlerKey = cacheStringFunction((str) => (str ? `on${capitalize(str)}` : ``));

const result = toHandlerKey('click');
console.log(result, 'result'); // 'onClick'

3.27 hasChanged, чтобы определить, есть ли изменение

hasChangedЭтот метод стоит упомянуть: когда я только писал эту статью, он еще не использовался.Object.is, увидим позжеgitзапись нашла кого-тоупомянуть PR.превратиться вObject.isДа, Юда слился.

const hasChanged = (value, oldValue) => !Object.is(value, oldValue);

Ниже приведен исходный код.

// compare whether a value has changed, accounting for NaN.
const hasChanged = (value, oldValue) => value !== oldValue && (value === value || oldValue === oldValue);
// 例子:
// 认为 NaN 是不变的
hasChanged(NaN, NaN); // false
hasChanged(1, 1); // false
hasChanged(1, 2); // true
hasChanged(+0, -0); // false
// Obect.is 认为 +0 和 -0 不是同一个值
Object.is(+0, -0); // false           
// Object.is 认为  NaN 和 本身 相比 是同一个值
Object.is(NaN, NaN); // true
// 场景
// watch 监测值是不是变化了

// (value === value || oldValue === oldValue)
// 为什么会有这句 因为要判断 NaN 。认为 NaN 是不变的。因为 NaN === NaN 为 false

согласно сhasChangedДавайте продолжим видеть это:Object.is API.

Object.is(value1, value2) (ES6)

Этот метод используется для сравнения, являются ли два значения строго равными. Он ведет себя в основном так же, как оператор строгого сравнения (===). Отличий всего два: одно+0не равно-0, ноNaNравно самому себе.

Object.is('若川', '若川'); // true
Object.is({},{}); // false
Object.is(+0, -0); // false
+0 === -0; // true
Object.is(NaN, NaN); // true
NaN === NaN; // false

ES5Его можно развернуть с помощью следующего кодаObject.is.

Object.defineProperty(Object, 'is', {
    value: function() {x, y} {
        if (x === y) {
           // 针对+0不等于-0的情况
           return x !== 0 || 1 / x === 1 / y;
        }
        // 针对 NaN的情况
        return x !== x && y !== y;
    },
    configurable: true,
    enumerable: false,
    writable: true
});

Это можно объяснить на примере

3.28 invokeArrayFns выполняет функции в массиве

const invokeArrayFns = (fns, arg) => {
    for (let i = 0; i < fns.length; i++) {
        fns[i](arg);
    }
};

// 例子:
const arr = [
    function(val){
        console.log(val + '的博客地址是:https://lxchuan12.gitee.io');
    },
    function(val){
        console.log('百度搜索 若川 可以找到' + val);
    },
    function(val){
        console.log('微信搜索 若川视野 可以找到关注' + val);
    },
]
invokeArrayFns(arr, '我');

Зачем так писать, мы обычно просто выполняем функцию.

Функции хранятся в массивах, а функции на самом деле являются данными. Такой способ написания облегчает унифицированное выполнение нескольких функций.

3.29 def определяет свойства объекта.

const def = (obj, key, value) => {
    Object.defineProperty(obj, key, {
        configurable: true,
        enumerable: false,
        value
    });
};

Object.definePropertyочень важныйAPI. Существует также определение нескольких свойствAPI:Object.defineProperties(obj, props) (ES5)

Object.definePropertyЗадействованы более важные точки знаний.
существуетES3, за исключением некоторых встроенных свойств (таких как:Math.PI), все свойства объекта могут быть изменены, вставлены, удалены в любое время. существуетES5, мы можем указать, можно ли изменить или удалить свойство — до этого это была привилегия для встроенных свойств.ES5введен вдескриптор свойстваПонятие , с помощью которого мы можем иметь больший контроль над определяемыми нами свойствами. Этидескриптор свойства(особенности) включают в себя:

value- Значение, возвращаемое при попытке получить свойство.
writable- Является ли свойство доступным для записи.
enumerable- это свойство находится вfor inБудет ли цикл пронумерован.
configurable- Можно ли удалить атрибут.
set()- Функция, вызываемая операцией обновления этого свойства.
get()- Функция, вызываемая при получении значения свойства.

Кроме того,дескриптор данных(где свойства:enumerable,configurable,value,writable)а такжедескриптор доступа(где имуществоenumerable,configurable,set(),get()) являются взаимоисключающими. в определенииset()а такжеget()После этого дескриптор будет думать, что определена операция доступа, которая определяетvalueа такжеwritableМогувызвать ошибку.

Ниже приведеныES3Свойства стиля определяются следующим образом:

var person = {};
person.legs = 2;

Вот эквивалентный проход ES5дескриптор данныхКак определить свойства:

var person = {};
Object.defineProperty(person, 'legs', {
    value: 2,
    writable: true,
    configurable: true,
    enumerable: true
});

Среди них, кроме значения по умолчанию значенияundefined, другие значения по умолчаниюfalse. Это означает, что если вы хотите таким образом определить доступное для записи свойство, вы должны явно установить для него значениеtrue. Кроме того, мы также можем передатьES5Дескриптор хранилища для определения:

var person = {};
Object.defineProperty(person, 'legs', {
    set:function(v) {
        return this.value = v;
    },
    get: function(v) {
        return this.value;
    },
    configurable: true,
    enumerable: true
});
person.legs = 2;

Таким образом, для описания свойств можно использовать много кода, и если мы хотим, чтобы другие не вмешивались в наши свойства, мы должны их использовать. Также не забывайте об обратной совместимости браузера.ES3аспекты рассмотрения. Например, с добавлениемArray.prototypeСвойства другие, мы не можем использовать его в старых браузерах.shimэта особенность. Кроме того, мы также можем (путем определенияnonmalleableсвойства), используйте эти дескрипторы в конкретных действиях:

var person = {};
Object.defineProperty(person, 'heads', {value: 1});
person.heads = 0; // 0
person.heads; // 1  (改不了)
delete person.heads; // false
person.heads // 1 (删不掉)

Другие описанные здесь будут описаны. Больше объектовAPIВы можете просмотреть эту статьюВесь API-анализ объектов JavaScript.

3.30 toNumber to Number

const toNumber = (val) => {
    const n = parseFloat(val);
    return isNaN(n) ? val : n;
};

toNumber('111'); // 111
toNumber('a111'); // 'a111'
parseFloat('a111'); // NaN
isNaN(NaN); // true

фактическиisNaNНамерение состоит в том, чтобы судить о том,NaNценность, но неточная.

Например:isNaN('a')дляtrue. такES6имеютNumber.isNaNЭтот метод суждения, чтобы компенсировать этотAPI.

Number.isNaN('a')  // false
Number.isNaN(NaN); // true

3.31 глобальный объект getGlobalThis

let _globalThis;
const getGlobalThis = () => {
    return (_globalThis ||
        (_globalThis =
            typeof globalThis !== 'undefined'
                ? globalThis
                : typeof self !== 'undefined'
                    ? self
                    : typeof window !== 'undefined'
                        ? window
                        : typeof global !== 'undefined'
                            ? global
                            : {}));
};

стать глобальнымthisнаправление.

Первое исполнение однозначно_globalThisдаundefined. Таким образом, будет выполнен следующий оператор присваивания.

если он существуетglobalThisзатем применитьglobalThis.MDN globalThis

если он существуетselfЗатем подать заявкуself. существуетWeb Workerнельзя получить доступ вwindowобъект, но мы можем пройтиselfдоступ кWorkerГлобальный объект в среде.

если он существуетwindow, затем применитьwindow.

если он существуетglobal, затем применитьglobal.Nodeокружающая среда, использованиеglobal.

Если ни один из них не существует, используйте пустой объект. Это может быть в среде апплета WeChat.

Возврат непосредственно к следующему выполнению_globalThis, не надо продолжать судить второй раз. Этому способу письма стоит научиться.

4. Напоследок порекомендуйте несколько статей и книг

Я рекомендую сначала я думаю, что это хорошоJavaScript APIнесколько статей и несколько книг, которые стоит прочитать.

Все API строк JavaScript полностью расшифрованы

[Подробная длинная статья] Все API-интерфейсы массивов JavaScript полностью расшифрованы

Руководство пользователя внешнего интерфейса регулярных выражений

Лао Яо: «Мини-книга по регулярным выражениям JavaScript» вышла!

Lao Yao Talks: Как выучить JavaScript?

Весь API-анализ объектов JavaScript Биография Лу Синя 12.git ee.IO/ is -object- ах...

MDN JavaScript

Продвинутое программирование с помощью JavaScript, 4-е издание

Полное руководство по JavaScript, 7-е издание

«Объектно-ориентированное программирование JavaScript 2»Объектно-ориентированный очень подробно.

Учитель Руан Ифэн: «Вводный курс по ES6»

Учебник по современному JavaScript

«JavaScript, которого вы не знаете», том 1

Шаблоны проектирования JavaScript и практика разработки

Я также испытал это, так как я не мог читать книги. Пишите статьи, чтобы поделиться.

Мой способ чтения книг: читать несколько книг одновременно и читать одни и те же и похожие главы, например функции. Прочитав эту книгу, вы можете ее не понять.Прочитав следующую книгу, вы в основном поймете ее после прочтения нескольких книг.Если вы не поняли ее один раз, прочитайте ее несколько раз, чтобы не забыть и закрепить соответствующие главы. Конечно, сначала было тяжело читать книгу, да и читать было трудно. Большинство из этих книг доступны для чтения в WeChat.Если вы привыкли читать бумажные книги, вы можете купить их.

Здесь вы можете посмотреть несколько видео и попрактиковаться в некоторых простых проектах.

Например: вы можете зарегистрироваться самостоятельноgithubАккаунт, разделенный на главы и подразделы, скопируйте код в книгу, отправьте наgithub, чем больше вы практикуетесь, тем больше вы чувствуете.

Другой примерСайт онлайн-обучения китайскому языку freeCodeCampВеб-сайт. Чтение книг — очень хороший способ систематического обучения. Позже я просто больше смотрел на исходный код и писал статьи, которыми делился со всеми.

5. Резюме

В основном через обучениеsharedДесятки полезных функций под модулем, таких как:isPromise,makeMap,cacheStringFunction,invokeArrayFns,def,getGlobalThisи т.п.

также поделилсяvueНавыки отладки исходного кода, порекомендуйте некоторые книги и способы чтения книг.

Исходный код тоже не так страшен. Обычно мы можем часто использовать эти функции инструмента в нашей работе. Изучив некоторый простой исходный код, расширив при этом свой кругозор, вы также сможете внедрить его в свою работу и разработку, и преимущества относительно высоки.


о

Автор: Чанг ИВакагаваНазвание смешано в реках и озерах. добро пожаловать, чтобы добавить меня wechatruochuan12. По дороге на фронт | Знаю очень мало, только хорошо учусь.
Обратите внимание на паблик аккаунта Ruochuan Vision, Изучайте исходный код вместе каждую неделю, научитесь читать исходный код и станьте продвинутым фронтендом.
Блог Вакагавы
segmentfaultКолонна Вакагава Видение, открылВидение ВакагаваКолонка, добро пожаловать на внимание ~
Колонка самородков, добро пожаловать, обратите внимание~
Колонна видений Чжиху Руочуань, открылВидение ВакагаваКолонка, добро пожаловать на внимание ~
github blog, спроситьstar^_^~