关闭

如何禁止JavaScript对象重写?

时间: 2018-06-27阅读: 1091标签: 对象


由于JavaScript的灵活性,我们可以轻易地重写(override)一些于其他人定义的对象(object)。换句话说,任何人都可以重写我们所定义的对象。这是一个非常强大的特性,许多开发者都有兴趣试试,来拓展或者修改某些对象的行为。例如,DOM方法document.getElementById()都可以被重写。一般来讲,我们应该避免这样做,因为这会导致代码很难维护,并且会留下一些难于发现的BUG。ECMAScript 5引入了一些方法,允许开发者限制对象重写。如果你在开发一些工具库比如jQueryfundebug等, 或者你的开发团队非常大,本文介绍的这些方法将非常有用。


不要重写他人的对象

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

// 示例代码1
window.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(),这会导致非常严重的后果。

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

// 示例代码2
Math.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()可以查看某个对象是否可以增加方法或者属性。

// 示例代码3
var 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);  // undefined


song.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的对象新增属性时,会立即报错。广告:如果你希望实时监控应用中类似的错误,欢迎免费试用Fundebug

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 extensible
delete song.artist; // Uncaught TypeError: Cannot delete property 'artist' of #<Object>

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 #<Object> 
song.getLongTitle = function() // Uncaught TypeError: Cannot assign to read only property 'getLongTitle' of object '#<Object>'
{
    return "foobar";
};

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

  • IE 9+
  • Firefox 4+
  • Safari 5.1+
  • Chrome 7+
  • Opera 12+


站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/898

js之global 全局对象 方法

global 作为js的全局对象,但其是无法直接访问的,但是在浏览器中浏览器是将这个对象当做是window对象的一部分,即Date 等Global的属性使用window.Date 可访问到

Js判断对象和数组

在调用后端接口时,由于后端接口的不规范统一,接口最外层在没有数据时返回的是空数组(其实更想要的是空json对象,接口返回的data数据应该统一返回json对象,便于扩展),而在有数据时返回的是json对象

如何在 JavaScript 中使用对象的方法

JavaScript 中,对象是 键/值 对的集合。值可以包含属性和方法,并且可以包含所有其他 JavaScript 数据类型,例如字符串,数字和布尔值。JavaScript中的所有对象都来自父 Object 的构造函数。

为什么javascript中无法创建activexobject对象?

ActiveXObject()用于在IE或者IE内核下创建ActiveX控件对象,其创建的对象是基于控件的,所以创建该对象必须先安装控件。

JavaScript 防篡改对象

开发过程中,每个开发者定义的对象可能不想要被别的开发者所重写或者新增对象属性,这时候可以将对象变为防篡改对象,当然防篡改对象也有分级别的

js中Object.create vs new Function() 的区别

之前学习JavaScript 权威指南,说以后在JavaScript建立对象请使用Object.create() 尽量少使用 new Function() .这两个新建对象的方法到底有什么不同呢?new 方式实现方式,实际上是先新建了一个Object对象,再用这个对象继承至Base,最后再绑定this.

在原生JavaScript中创建不可变对象

Javascript是一种灵活的语言,你可以重新定义任何东西,但是当项目变得复杂时,我们会发现可变数据结构的问题。随着JavaScript的最新版本的发布这种情况发生了改变。现在可以创建不可变的对象了。本文介绍如何用三种不同的方法来做。

js基础_究竟什么是变量对象,什么是活动对象?

在写程序的时候会定义很多变量和函数,那js解析器是如何找到这些变量和函数的?变量对象是与执行上下文对应的概念,在执行上下文的创建阶段,它依次存储着在上下文中定义的以下内容:函数的所有形参、所有函数声明、所有变量声明

js中new的本质

用 var anObject = new aFunction() 形式创建对象的过程实际上可以分为三步: 第一步是建立一个新对象; 第二步将该对象内置的原型对象设置为构造函数prototype引用的那个原型对象; 第三步就是将该对象作为this参数调用构造函数,完成成员设置等初始化工作。

用 global This访问全局对象

JavaScript 语言越来越被广泛地用于各种环境中。除了 Web 浏览器(这是 JavaScript 的最常见的宿主环境类型)之外,你还可以在服务器,智能手机甚至机器人硬件中运行 JavaScript 程序。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!