个性化阅读
专注于IT技术分析

如何防止修改JavaScript中的对象并防止它们在控制台中访问

本文概述

有多种方法可以根据你的需要锁定对象。对象对象(尽管有冗余), 具有一些有用的功能, 可让你锁定对象。

  • 对象冻结
  • 物体密封
  • Object.preventExtensions

对于本文中的所有示例, 我们将使用以下对象:

var myBankAccount = {
    user: {
        fullname : "Bruce wayne", age: 26, occupation: {
            day: "Philanthropist billionaire", night: "I'm Batman"
        }
    }, multipleAccounts: true, accounts : [
        {
            money: (9999999999999999), currency : "EUR"
        }, {
            money: (9999999999999999), currency : "USD"
        }
    ]
};

对象冻结

冻结方法冻结对象(感谢队长)。

如何防止修改JavaScript中的对象并防止它们在控制台中访问1

此方法可防止向其添加新属性, 防止删除现有属性, 并防止更改现有属性(或其可枚举性, 可配置性或可写性)。本质上, 对象是不可变的。该方法返回冻结的对象。

// Add a property before being frozen
myBankAccount.bankName = "Gotham Merchant Bank";

// Shows the value in the object as the property
// was created before the object has been frozen
console.log(myBankAccount.bankName);

// Freeze the object
Object.freeze(myBankAccount);
/**
 * Now the object cannot be modified, deleted written
 */
myBankAccount.flushMethod = function(){
  SendAllMoneyToJokerAccount();
};

// Will be neither deleted !
delete myBankAccount.bankName;

// Throws error, method doesn't exist.
myBankAccount.flushMethod();

请注意, 仅冻结对象作为第一个参数。如果冻结对象的值是一个对象, 则即使你也冻结它们, 也可以对其进行修改。如果尝试修改myBankAccount.user, 则可以在该对象内部添加属性。

// Freeze object
Object.freeze(myBankAccount);

// The user property is an object, and you didn't freeze it Too
// to solve use Object.freeze(myBankAccount.user)
myBankAccount.user.flushMethod = function(){
    SendAllMoneyToJokerAccount();
};

// Money succesfully transfered :(
// You disappoint Batman
myBankAccount.user.flushMethod();

Object.preventExtensions

preventExtensions方法可防止将新属性添加到对象(即防止将来对该对象进行扩展)。

// Add property before being nonExtensible
myBankAccount.newValue = 12;

// Disallow new properties to the bank account
Object.preventExtensions(myBankAccount);

// Silently ignored or TypeError
myBankAccount.flushAccount = function(){
   sendMoneyToJokerAccount();
};

console.log(myBankAccount.newValue);// Output :12

// Method doesn't exist
myBankAccount.flushAccount();

物体密封

密封方法可密封对象, 从而防止向其添加新属性并将所有现有属性标记为不可配置。只要可写, 当前属性的值仍可以更改。

// Seal object
Object.seal(myBankAccount);

// Changing property values on a sealed object still works.
myBankAccount.multipleAccounts = false;

// But you can't convert data properties to accessors, or vice versa.
Object.defineProperty(myBankAccount, 'foo', { get: function() { return 'hey'; } }); // throws a TypeError

delete myBankAccount.user; // throws a TypeError 
myBankAccount.newPropertyToAdd = 'qwe'; // throws a TypeError

快速比较和注释

函数 使对象不可扩展 每个属性的可配置设置为false
Object.preventExtensions No
物体密封
对象冻结
  • 除非冻结对象, 否则冻结对象的子对象是可修改的。
  • 使用Object.seal的原型链保持不变。但是, __proto__属性也是密封的。
  • 属性仍然可以添加到对象原型。但是, 在对象上调用preventExtensions也将阻止对其__proto__属性的扩展。

Object变量具有一种有用的方法来检查对象是否使用了任何先前的功能:

  • Object.isFrozen(myObj)。
  • Object.isSealed(myObj)。
  • Object.isExtensible(myObj)。

除非你在代码中使用严格模式(” use strict”;), 否则不会在控制台中引发任何错误, 因为所有内容都将被静默忽略。但是, 在严格模式下, 如果尝试在不可扩展的对象中添加属性等来完成任务, 则会出现类型错误。

防止在控制台中访问变量

如果你担心有人可以签出你的代码并在控制台中进行修改, 则只需将你的代码包装在一个匿名函数中即可。这将阻止其出现在控制台中, 因此其他开发人员将无法以这种方式访问​​代码。

分析以下代码:

<input type="button" id="transfer" value="TransferToAccount" />
<input type="text" id="account" />
<input type="text" id="ammount" />

<script>
var allow_transaction = false;
var MySuperBankObject = {
    person: "Bruce", account: 123123, money: (9999.99), sendMoneyToAccount : function(idAccount, amount){
        if(amount <= this.money){
            allow_transaction = true;
            TransferToAccount(this.account, idAccount, amount);
        }else{
            throw new Error("Too much money. You don't have all that money :(.");
        }
    }
};

function TransferToAccount(source_account, target_account, amount){
    if(!allow_transaction){
        throw new Error("The transaction needs to be verified");
    }

    console.log(amount + " Dollars succesfully transfered to " + target_account + " account from "+ source_account);
}

// Onclick, do transaction
document.getElementById("transfer").addEventListener("click", function(){
    // get required info
    var amount = document.getElementById("amount").value;
    var accountTarget = document.getElementById("account").value;
    // Do transaction 
    MySuperBankObject.sendMoneyToAccount(parseInt(accountTarget), parseFloat(amount));
}, false);
</script>

如果你在文档中包含此代码, 并且某人决定读取该文件的代码, 则由于MySuperBankObject对象是全局公开的, 因此他们可以在控制台中查找并执行以下代码:

防止在控制台中访问变量

没有人想要吗, 对吗?为了防止这种情况(尽管该代码在浏览器中可见, 但是无法修改), 将先前的代码包装在一个匿名函数中:

(function(){
   /**
    * All the code that needs to be unexposed in the console here.
    */
})(); // Send parameters inside the function if you need to

现在将前一个包裹在一个匿名函数中:

<input type="button" id="transfer" value="TransferToAccount" />
<input type="text" id="account" />
<input type="text" id="ammount" />

<script>
(function(){

var allow_transaction = false;
var MySuperBankObject = {
    person: "Bruce", account: 123123, ....
....

})();
</script>

有用吗?如果开发人员尝试在控制台中获取mySuperBankObject, 他将面临以下问题:

未定义的控制台

该代码将按预期工作, 但是变量不再在控制台中公开。还要注意, 即使你的代码有弱点(getter和setter的配置错误, 即愚蠢的全局函数如getMySuperBankObject …)并且具有足够的知识, 但是仍不能被轻易修改, 尽管开发人员仍可以轻松地对其进行修改。 。精简代码以降低可读性。

最后, 请不要处理带有此帖子中所发布代码的银行帐户, 谢谢!

玩得开心

赞(0)
未经允许不得转载:srcmini » 如何防止修改JavaScript中的对象并防止它们在控制台中访问

评论 抢沙发

评论前必须登录!