如何使一个对象属性无法扩展、修改和删除?
之前在使用Angular 8 时,遇到过一个问题:
在路由中取出路由里的路径参数可以使用this.activatedRoute.snapshot
中的queryParams
属性,即路径中?
号后面的参数。但当时的需求是取完之后要删除某个参数(id)的值,所以想当然地进行如下操作
const params = this.activatedRoute.snapshot.queryParams;
delete(params.id);
运行之后打印params
发现并没有生效,参数id还是在路径上,并没有被删除。
查找Angular源码https://github.com/angular/angular
,
发现有关new ActivatedRouteSnapshot()
的地方代码是:
if (route.path === '**') {
const params = segments.length > 0 ? last(segments)!.parameters : {};
snapshot = new ActivatedRouteSnapshot(
segments, params, Object.freeze({...this.urlTree.queryParams}), this.urlTree.fragment!,
getData(route), getOutlet(route), route.component!, route,
getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + segments.length,
getResolve(route));
} else {
const result = match(rawSegment, route, segments);
if (!result.matched) {
return null;
}
consumedSegments = result.consumedSegments;
rawSlicedSegments = segments.slice(result.lastChild);
snapshot = new ActivatedRouteSnapshot(
consumedSegments, result.parameters, Object.freeze({...this.urlTree.queryParams}),
this.urlTree.fragment!, getData(route), getOutlet(route), route.component!, route,
getSourceSegmentGroup(rawSegment),
getPathIndexShift(rawSegment) + consumedSegments.length, getResolve(route));
}
// 而ActivatedRouteSnapshot的constructor是
constructor(
/** The URL segments matched by this route */
public url: UrlSegment[],
public params: Params,
/** The query parameters shared by all the routes */
public queryParams: Params,
/** The URL fragment shared by all the routes */
public fragment: string,
/** The static and resolved data of this route */
public data: Data,
/** The outlet name of the route */
public outlet: string,
/** The component of the route */
public component: Type<any>|string|null, routeConfig: Route|null, urlSegment: UrlSegmentGroup,
lastPathIndex: number, resolve: ResolveData) {
this.routeConfig = routeConfig;
this._urlSegment = urlSegment;
this._lastPathIndex = lastPathIndex;
this._resolve = resolve;
}
其中的constructor中的queryParams在上面new的时候传入的是Object.freeze({...this.urlTree.queryParams})
, 这就很清楚了,是Object.freeze
方法阻止了对参数的删除。
那么除了
Object.freeze
,还有哪些方法可以对对象的属性扩展、修改和删除做限制呢?
扩展性:阻止扩展-Object.preventExtensions()
可以修改+删除
通过Object.isExtensible()来查看一个对象是否具有扩展性
密封性:阻止删除+扩展-Object.seal()
不能修改已有属性的可枚举性、可配置性、可写性,但可能可以修改已有属性的值
通过Object.isSealed()来查看一个对象是否具有密封性
冻结性:阻止修改+删除+扩展-Object.freeze()
完全只读
通过Object.isFrozen()来查看一个对象是否具有冻结性
Object.getOwnPropertyDescriptors()
来获取:
补充:上述可枚举性、可配置性、可写性,可通过let a = {test: 'hello', test2: 'world'};
//test: {value: "hello", writable: true, enumerable: true, configurable: true}
//test2: {value: "world", writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptors(a));
- value
- 该属性的值(仅针对数据属性描述符有效)
- writable
- 当且仅当属性的值可以被改变时为true。(仅针对数据属性描述有效)
- configurable
- 当且仅当指定对象的属性描述可以被改变或者属性可被删除时,为true。
- enumerable
- 当且仅当指定对象的属性可以被枚举出时,为 true。
- get
- 获取该属性的访问器函数(getter)。如果没有访问器, 该值为undefined。(仅针对包含访问器或设置器的属性描述有效)
- set
- 获取该属性的设置器函数(setter)。 如果没有设置器, 该值为undefined。(仅针对包含访问器或设置器的属性描述有效)
以上就是有关给对象限制属性操作的方法。