博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何禁止JavaScript对象重写?
阅读量:4117 次
发布时间:2019-05-25

本文共 3598 字,大约阅读时间需要 11 分钟。

来源 | http://piotrwalat.net/

翻译 | Fundebug

由于JavaScript的灵活性,我们可以轻易地重写(override)一些于其他人定义的对象(object)。

换句话说,任何人都可以重写我们所定义的对象。

这是一个非常强大的特性,许多开发者都有兴趣试试,来拓展或者修改某些对象的行为。

例如,DOM方法document.getElementById()都可以被重写。

一般来讲,我们应该避免这样做,因为这会导致代码很难维护,并且会留下一些难于发现的BUG。

ECMAScript 5引入了一些方法,允许开发者限制对象重写。

如果你在开发一些工具库比如jQuery, fundebug等, 或者你的开发团队非常大,本文介绍的这些方法将非常有用。

不要重写他人的对象

不要重写他人的对象,这是JavaScript的黄金法则。比如,当你重写了一个方法,则很可能这会影响依赖于该方法的库,这会让其他开发者非常困惑。

// 示例代码1window.originalAlert = window.alert;  window.alert = function(msg) {      if (typeof msg === "string") {        return console.log(msg);    }    return window.originalAlert(msg);};alert('ooh so awesome'); // 参数为字符串时,打印到控制台 alert(3.14); // 参数为其他类型时,弹出对话框

在示例代码1中,我修改了windows.alert:参数为字符串时,打印到控制台;参数为其他类型时,弹出对话框。这样的修改显然会影响其他使用alert方法的开发者。

如果你修改的是DOM对象比如getElementById(),这会导致非常严重的后果。

如果你只是为对象添加新的方法,这也会导致问题。

// 示例代码2Math.cube = function(n) {      return Math.pow(n, 3);};console.log(Math.cube(2)); // 8

这样做最大的问题是有可能在未来导致命名冲突。尽管Math对象目前并没有cube方法,下一个版本的JavaScript标准也许会增加cube方法(当然可能性不大),这就意味着我们会把原生cube方法给替代了。

有一个真实的案例,Prototype库定义了document.getElementsByClassName()方法,而这个方法后来被加入了JavaScript标准。

不幸的是,我们无法阻止其他开发者重写我们定义的对象,这时我们就需要本文介绍的这些方法了:

首先,我们不妨通过一个表格对比一下Object.preventExtensions()、Object.seal()和Object.freeze():

方法 禁止增加属性 禁止删除属性 禁止修改属性
Object.preventExtensions()
Object.seal()
Object.freeze()

Object.preventExtensions()

使用Object.preventExtensions(),可以禁止给对象添加新的方法或者属性。注意,修改或者删除对象已经存在的方法或者属性是没有问题的。使用Object.isExtensible()可以查看某个对象是否可以增加方法或者属性。

// 示例代码3var song = {      title: 'Hope Leaves',    artist: 'Opeth'};console.log(Object.isExtensible(song)); //true  Object.preventExtensions(song);  console.log(Object.isExtensible(song)); //false  song.album = 'Damnation';console.log(song.album);  // undefinedsong.play = function() {      console.log('ahh soo awesome');};song.play(); // TypeError: song.play is not a function

由示例代码3可知,执行Object.preventExtensions()之后,为song对象新增album以及play方法都失败了!

但是,当我们为song新增属性或者方法时,并没有报错。当我们使用了”use strict”采用严格模式时,情况就不一样了:

// 示例代码4"use strict";var song = {      title: 'Hope Leaves',    artist: 'Opeth'};Object.preventExtensions(song);  song.album = 'Damnation'; // Uncaught TypeError: Cannot add property album, object is not extensible

在严格模式下,给已经Object.preventExtensions的对象新增属性时,会立即报错。

Object.seal()

使用Object.seal(),可以禁止给对象添加属性或者方法(这一点与Object.preventExtension()的作用一致),同时禁止删除对象已经存在的属性或者方法。

// 示例代码5"use strict"var song = {    title: 'Hope Leaves',    artist: 'Opeth'};Object.seal(song);console.log(Object.isExtensible(song)); //false  console.log(Object.isSealed(song)); //true  song.album = 'Damnation'; // Uncaught TypeError: Cannot add property album, object is not extensibledelete song.artist; // Uncaught TypeError: Cannot delete property 'artist' of #

Object.freeze()

使用Object.freeze(),可以禁止为对象增加属性或者方法(这一点与Object.preventExtension()的作用一致),同时禁止删除对象已经存在的属性或者方法(这一点与Object.seal()的作用一致),另外还禁止修改已经存在的属性或者方法。

// 示例代码6"use strict"var song = {    title: 'Hope Leaves',    artist: 'Opeth',    getLongTitle: function(){        return this.artist + " - " + this.title;    }};Object.freeze(song);console.log(Object.isExtensible(song)); // false  console.log(Object.isSealed(song)); // true  console.log(Object.isFrozen(song)); // true  song.album = 'Damnation'; // Uncaught TypeError: Cannot add property album, object is not extensible  delete song.artist; // Uncaught TypeError: Cannot delete property 'artist' of # song.getLongTitle = function() // Uncaught TypeError: Cannot assign to read only property 'getLongTitle' of object '#'{    return "foobar";};

主流浏览器的最新版本都支持这些方法:

  • IE 9+

  • Firefox 4+

  • Safari 5.1+

  • Chrome 7+

  • Opera 12+

本文完〜

转载地址:http://hvbpi.baihongyu.com/

你可能感兴趣的文章
Spring框架的ImportSelector到底可以干嘛
查看>>
Mysql中下划线问题
查看>>
微信小程序中使用npm过程中提示:npm WARN saveError ENOENT: no such file or directory
查看>>
Xcode 11 报错,提示libstdc++.6 缺失,解决方案
查看>>
idea的安装以及简单使用
查看>>
Windows mysql 安装
查看>>
python循环语句与C语言的区别
查看>>
Vue项目中使用img图片和background背景图的使用方法
查看>>
vue 项目中图片选择路径位置static 或 assets区别
查看>>
vue项目打包后无法运行报错空白页面
查看>>
Vue 解决部署到服务器后或者build之后Element UI图标不显示问题(404错误)
查看>>
element-ui全局自定义主题
查看>>
facebook库runtime.js
查看>>
vue2.* 中 使用socket.io
查看>>
openlayers安装引用
查看>>
js报错显示subString/subStr is not a function
查看>>
高德地图js API实现鼠标悬浮于点标记时弹出信息窗体显示详情,点击点标记放大地图操作
查看>>
初始化VUE项目报错
查看>>
vue项目使用安装sass
查看>>
HTTP和HttpServletRequest 要点
查看>>