From f3b9ebf57163bb4ccb1416e58d58adfbb3bf8c84 Mon Sep 17 00:00:00 2001 From: Zong Date: Sun, 9 May 2021 10:46:11 +0800 Subject: [PATCH] fix: use more reasonable type inference (#1963) Use 'hasOwn' instead of 'hasOwnProperty' to complete more reasonable type inference and avoid possible bugs in the prototype chain. --- packages/color-picker/src/color.ts | 6 ++++-- packages/loading/src/index.ts | 3 ++- packages/message-box/src/messageBox.ts | 5 +++-- packages/table/src/store/watcher.ts | 3 ++- packages/table/src/table-column/watcher-helper.ts | 5 +++-- packages/table/src/table-layout.ts | 7 ++++--- packages/table/src/util.ts | 7 ++----- packages/tree/src/model/node.ts | 3 ++- packages/tree/src/model/tree-store.ts | 5 +++-- packages/upload/src/ajax.ts | 3 ++- packages/upload/src/upload.vue | 4 ++-- packages/virtual-list/src/builders/buildGrid.ts | 3 ++- packages/virtual-list/src/builders/buildList.ts | 3 ++- 13 files changed, 33 insertions(+), 24 deletions(-) diff --git a/packages/color-picker/src/color.ts b/packages/color-picker/src/color.ts index 6b3c651473..63e9060f5e 100644 --- a/packages/color-picker/src/color.ts +++ b/packages/color-picker/src/color.ts @@ -1,3 +1,5 @@ +import { hasOwn } from '@vue/shared' + const hsv2hsl = function(hue: number, sat: number, val: number) { return [ hue, @@ -169,7 +171,7 @@ export default class Color { options = options || {} as Options for (const option in options) { - if (options.hasOwnProperty(option)) { + if (hasOwn(options, option)) { this[option] = options[option] } } @@ -180,7 +182,7 @@ export default class Color { set(prop: {[key: string]: any;} | any, value?: number) { if (arguments.length === 1 && typeof prop === 'object') { for (const p in prop) { - if (prop.hasOwnProperty(p)) { + if (hasOwn(prop, p)) { this.set(p, prop[p]) } } diff --git a/packages/loading/src/index.ts b/packages/loading/src/index.ts index 26c21a56c4..e417fc478f 100644 --- a/packages/loading/src/index.ts +++ b/packages/loading/src/index.ts @@ -1,4 +1,5 @@ import { nextTick } from 'vue' +import { hasOwn } from '@vue/shared' import { createLoadingComponent } from './createLoadingComponent' import type { ILoadingGlobalConfig, ILoadingInstance, ILoadingOptions } from './loading.type' import { addClass, getStyle, removeClass } from '@element-plus/utils/dom' @@ -122,7 +123,7 @@ const Loading = function (options: ILoadingOptions = {}): ILoadingInstance { // after instance render, then modify visible to trigger transition nextTick().then(() => { - instance.visible.value = options.hasOwnProperty('visible') ? options.visible : true + instance.visible.value = hasOwn(options, 'visible') ? options.visible : true }) if (options.fullscreen) { diff --git a/packages/message-box/src/messageBox.ts b/packages/message-box/src/messageBox.ts index ea42cb0535..f00e3b9e3a 100644 --- a/packages/message-box/src/messageBox.ts +++ b/packages/message-box/src/messageBox.ts @@ -1,4 +1,5 @@ import { h, watch, render } from 'vue' +import { hasOwn } from '@vue/shared' import MessageBoxConstructor from './index.vue' import isServer from '@element-plus/utils/isServer' import { isVNode, isString } from '@element-plus/utils/util' @@ -85,8 +86,8 @@ const showMessage = (options: any) => { } & MessageBoxState> for (const prop in options) { - if (options.hasOwnProperty(prop) && !vm.$props.hasOwnProperty(prop)) { - vm[prop] = options[prop] + if (hasOwn(options, prop) && !hasOwn(vm.$props, prop)) { + vm[prop as string] = options[prop] } } diff --git a/packages/table/src/store/watcher.ts b/packages/table/src/store/watcher.ts index 04c7e4c1ca..2a60157719 100644 --- a/packages/table/src/store/watcher.ts +++ b/packages/table/src/store/watcher.ts @@ -1,4 +1,5 @@ import { ref, getCurrentInstance, unref, watch } from 'vue' +import { hasOwn } from '@vue/shared' import { getKeysMap, getRowIdentity, @@ -149,7 +150,7 @@ function useWatcher () { const selectedMap = getKeysMap(selection.value, rowKey.value) const dataMap = getKeysMap(data.value, rowKey.value) for (const key in selectedMap) { - if (selectedMap.hasOwnProperty(key) && !dataMap[key]) { + if (hasOwn(selectedMap, key) && !dataMap[key]) { deleted.push(selectedMap[key].row) } } diff --git a/packages/table/src/table-column/watcher-helper.ts b/packages/table/src/table-column/watcher-helper.ts index 46cdd1477f..852868638c 100644 --- a/packages/table/src/table-column/watcher-helper.ts +++ b/packages/table/src/table-column/watcher-helper.ts @@ -1,4 +1,5 @@ import { watch, getCurrentInstance, ComputedRef } from 'vue' +import { hasOwn } from '@vue/shared' import { TableColumnCtx, TableColumn } from '../table.type' function useWatcher(owner: ComputedRef, props_: TableColumnCtx) { @@ -16,7 +17,7 @@ function useWatcher(owner: ComputedRef, props_: TableColumnCtx) { Object.keys(allAliases).forEach(key => { const columnKey = aliases[key] - if (props_.hasOwnProperty(columnKey)) { + if (hasOwn(props_, columnKey)) { watch( () => props_[columnKey], newVal => { @@ -54,7 +55,7 @@ function useWatcher(owner: ComputedRef, props_: TableColumnCtx) { }, aliases) Object.keys(allAliases).forEach(key => { const columnKey = aliases[key] - if (props_.hasOwnProperty(columnKey)) { + if (hasOwn(props_, columnKey)) { watch( () => props_[columnKey], newVal => { diff --git a/packages/table/src/table-layout.ts b/packages/table/src/table-layout.ts index 7170d3c8fe..af5113e14d 100644 --- a/packages/table/src/table-layout.ts +++ b/packages/table/src/table-layout.ts @@ -1,4 +1,5 @@ import { nextTick, ref, isRef, Ref } from 'vue' +import { hasOwn } from '@vue/shared' import scrollbarWidth from '@element-plus/utils/scrollbar-width' import isServer from '@element-plus/utils/isServer' import { parseHeight } from './util' @@ -54,11 +55,11 @@ class TableLayout { this.fixedBodyHeight = ref(null) this.gutterWidth = scrollbarWidth() for (const name in options) { - if (options.hasOwnProperty(name)) { + if (hasOwn(options, name)) { if (isRef(this[name])) { - this[name].value = options[name] + this[name as string].value = options[name] } else { - this[name] = options[name] + this[name as string] = options[name] } } } diff --git a/packages/table/src/util.ts b/packages/table/src/util.ts index 19770c93f5..0097fce7dd 100644 --- a/packages/table/src/util.ts +++ b/packages/table/src/util.ts @@ -1,3 +1,4 @@ +import { hasOwn } from '@vue/shared' import { PopperInstance, IPopperOptions } from '@element-plus/popper' import { getValueByPath } from '@element-plus/utils/util' import { off, on } from '@element-plus/utils/dom' @@ -164,10 +165,6 @@ export const getKeysMap = function( return arrayMap } -function hasOwn(obj: AnyObject, key: string): boolean { - return Object.prototype.hasOwnProperty.call(obj, key) -} - export function mergeOptions(defaults: T, config: K): T & K { const options = {} as T & K let key @@ -175,7 +172,7 @@ export function mergeOptions(defaults: T, config: K): T & K { options[key] = defaults[key] } for (key in config) { - if (hasOwn(config, key)) { + if (hasOwn(config as unknown as Indexable, key)) { const value = config[key] if (typeof value !== 'undefined') { options[key] = value diff --git a/packages/tree/src/model/node.ts b/packages/tree/src/model/node.ts index fe6529c87f..5baacd4b09 100644 --- a/packages/tree/src/model/node.ts +++ b/packages/tree/src/model/node.ts @@ -1,4 +1,5 @@ import { reactive } from 'vue' +import { hasOwn } from '@vue/shared' import { markNodeData, NODE_KEY } from './util' import TreeStore from './tree-store' @@ -104,7 +105,7 @@ export default class Node { this.canFocus = false for (const name in options) { - if (options.hasOwnProperty(name)) { + if (hasOwn(options, name)) { this[name] = options[name] } } diff --git a/packages/tree/src/model/tree-store.ts b/packages/tree/src/model/tree-store.ts index dd3aad37df..8b9502f7a2 100644 --- a/packages/tree/src/model/tree-store.ts +++ b/packages/tree/src/model/tree-store.ts @@ -1,3 +1,4 @@ +import { hasOwn } from '@vue/shared' import Node from './node' import { getNodeKey } from './util' import { @@ -35,7 +36,7 @@ export default class TreeStore { this.currentNodeKey = null for (const option in options) { - if (options.hasOwnProperty(option)) { + if (hasOwn(options, option)) { this[option] = options[option] } } @@ -237,7 +238,7 @@ export default class TreeStore { const allNodes: Node[] = [] const nodesMap = this.nodesMap for (const nodeKey in nodesMap) { - if (nodesMap.hasOwnProperty(nodeKey)) { + if (hasOwn(nodesMap, nodeKey)) { allNodes.push(nodesMap[nodeKey]) } } diff --git a/packages/upload/src/ajax.ts b/packages/upload/src/ajax.ts index 1ef7560c2f..f92fcff7f2 100644 --- a/packages/upload/src/ajax.ts +++ b/packages/upload/src/ajax.ts @@ -1,3 +1,4 @@ +import { hasOwn } from '@vue/shared' import type { ElUploadProgressEvent, ElUploadRequestOptions, @@ -82,7 +83,7 @@ export default function upload(option: ElUploadRequestOptions) { const headers = option.headers || {} for (const item in headers) { - if (headers.hasOwnProperty(item) && headers[item] !== null) { + if (hasOwn(headers, item) && headers[item] !== null) { xhr.setRequestHeader(item, headers[item]) } } diff --git a/packages/upload/src/upload.vue b/packages/upload/src/upload.vue index 3a472cf449..d61b26fa93 100644 --- a/packages/upload/src/upload.vue +++ b/packages/upload/src/upload.vue @@ -27,7 +27,7 @@