JavaScript 单体内置对象(Global、Math)

Note:This article is my study note, without copyright,Most of the English content in the article originates from the
MDN_Global_Objects

单体内置对象

《JavaScript高级程序设计》:由ECMAScript实现提供的、不依赖于宿主环境的对象,这些对象在ECMAScript程序执行前就已经存在了。 意思是说开发人员无需显式地实例化内置对象,因为他们已经实例化了。Object、Array、String等都是内置对象,除此之外还有Global、Math

前面博文讲作用域提到过 Global Object

1. Global对象

Global(全局)对象是ECMAScript中特殊的一个对象,不管你从什么角度看这个对象都是不存在的。Global对象某种意义上作为一种 “兜底儿对象” 来定义的。换句话说不属于任何其他对象的属性和方法,最终都是它的属性和方法。事实上没有全局变量和全局函数;所有全局作用域中定义的属性和函数,都是Global对象的属性,像isNaN()、isFinite()、parseFloat()、parseInt()实际上都是Global对象的方法,除此之外,还有:

1.1. URI编码方法

注意不是URL

有时候访问自己服务器上的中文名资源,复制网址后粘贴却变成了没有中文的地址,其实这和Global对象的编码方法encodeURI(str)encodeURIComponent(str)有关,这可以对URI(Uniform Resource Identifiers)进行编码,它们用特殊的字符替换无效的字符,使浏览器可以接受和理解

一般用 encodeURIComponent 较多,举个例子

      // 编码
      encodeURI('http://www.yama.gz.cn/resourse/作者.jpeg')
      // http://www.yama.gz.cn/resourse/%E4%BD%9C%E8%80%85.jpeg
      encodeURIComponent('http://www.yama.gz.cn/resourse/作者.jpeg')
      // http%3A%2F%2Fwww.yama.gz.cn%2Fresourse%2F%E4%BD%9C%E8%80%85.jpeg

      // 解码
      decodeURI('"http://www.yama.gz.cn/resourse/%E4%BD%9C%E8%80%85.jpeg"')
      // 没问题:http://www.yama.gz.cn/resourse/作者.jpeg"
      decodeURI("http%3A%2F%2Fwww.yama.gz.cn%2Fresourse%2F%E4%BD%9C%E8%80%85.jpeg")
      // 有问题:http%3A%2F%2Fwww.yama.gz.cn%2Fresourse%2F作者.jpeg
      // 发现使用decodeURI去解码使用encodeURIComponent编码的方法出现了问题
      decodeURIComponent('http://www.yama.gz.cn/resourse/%E4%BD%9C%E8%80%85.jpeg')
      // 没问题:http://www.yama.gz.cn/resourse/作者.jpeg
      decodeURIComponent("http://www.yama.gz.cn/resourse/%E4%BD%9C%E8%80%85.jpeg")
      // http://www.yama.gz.cn/resourse/作者.jpeg

与而这对应的两个解码方法有decodeURIdecodeURIComponent,其中decodeURI只能对使用encodeURI() 编码的字符进行解码,而decodeURIComponent由于他对应的编码方法非常全,所以它可以解码任何特殊字符的编码。

1.2. eval () 方法

MDN_Global_Objects/eval

eval() is a function property of the global object. eval() 方法用于接受一个字符串参数(这个参数可以不用加引号),这个参数将会作为JS代码被执行。

If the argument represents one or more JavaScript statements, eval() evaluates(评估) the statements. Do not call eval() to evaluate an arithmetic(算数) expression; JavaScript evaluates arithmetic expressions automatically(自动地).

If you use the eval function indirectly(间接地), by invoking(调用) it via(通过) a reference(引用) other than eval(除eval之外), as of ECMAScript 5 it works in the global scope(全局范围) rather than(而不是) the local scope(局部范围). This means, for instance, that function declarations create global functions, and that the code being evaluated doesn’t have access to local variables within the scope where it’s being called.

      function test() {
         var x = 2,
            y = 4;
         console.log(eval('x + y'));
         // 输出:6
         var geval = eval;
         console.log(geval('x + y'));
         // 输出:ReferenceError : `x` is undefined
         // 这时候geval就是除eval之外的其他引用,注意这点
         (0, eval)('x + y'); // another example of Indirect call
      }
      test();

在《JavaScript高级程序设计》中提到这是一个危险的函数,eval可能导致被运行恶意的代码,并且它本身的速度比较慢。
在必须使用的地方可以使用 window.Function() 代替它。

Every JavaScript function is actually a Function object. This can be seen with the code:
(function(){}).constructor === Function
which returns true.

Function 构造函数创建一个新的 Function 对象。直接调用此构造函数可用动态创建函数,但会遇到和 eval 类似的的安全问题和(相对较小的)性能问题。然而,与 eval 不同的是,Function 创建的函数只能在全局作用域中运行。
Function 创建的函数明确只能在全局作用域中运行,所以不用思考太多。

(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval)有许多细节值得看看

MDN 原话:

eval() is a dangerous function, which executes the code it’s passed with the privileges(特权) of the caller. If you run eval() with a string that could be affected by a malicious party, you may end up running malicious code on the user’s machine with the permissions of your webpage / extension. More importantly, a third-party code can see the scope in which eval() was invoked, which can lead to possible attacks in ways to which the similar Function is not susceptible.

eval() is also slower than the (备择方案,其他方法), since it has to invoke(调用) the JavaScript interpreter(解释器), while many other constructs(结构) are optimized(优化) by modern JS engines.

Additionally, modern javascript interpreters convert javascript to machine code. This means that any concept of variable naming gets obliterated(废除). Thus, any use of eval() will force the browser to do long expensive variable name lookups(变量名查找) to figure out where the variable exists in the machine code and set its value. Additonally, new things can be introduced to that variable through eval() such as changing the type of that variable, forcing the browser to re-evaluate all of the generated machine code to compensate(补偿).

Fortunately, there’s a very good alternative to eval(): simply using window.Function(). See this example of how to convert code using a dangerous eval() to using Function(), see below.

         // Better code without eval():
         // 使用window.Function,可以确定的是在全局中Date 引用自 window.Date()
         function looseJsonParse2(obj) {
            return Function('"use strict";return (' + obj + ')')();
         }
         console.log(looseJsonParse2(
            "{a:(4-1), b:function(){}, c:new Date()}"
         ))

         // Bad code with eval():
         // 使用eval并不能保证Date 安全地引用自 window.Date(),并且eval要慢得多
         function looseJsonParse1(obj) {
            return eval("(" + obj + ")");
         }
         console.log(looseJsonParse1(
            "{a:(4-1), b:function(){}, c:new Date()}"
         ))

         // 为什么无法确定使用eval是的Date是否安全?
         // 因为完全可以自己创建一个Date
         function Date(n){
            return ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"][n%7 || 0];
         }
         // Thus, in the eval() version of the code, the browser is forced to make the expensive lookup call to check to see if there are any local variables called Date(). This is incredibly inefficient(效率极低) compared to Function().

In a related circumstance, what if you actually wanted your Date() function to be able to be called from the code inside Function(). Should you just take the easy way out and fall back to eval()? No! Never. Instead try the approach below.

         function Date(n) {
            return ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"][n % 7 || 0];
         }

         function runCodeWithDateFunction(obj) {
            return Function('"use strict";return (' + obj + ')')()(
               Date
            );
         }
         console.log(runCodeWithDateFunction(
            "function(Date){ return Date(5) }"
         ))

1.3. Global Object的属性

1.4. window对象

ECMAScript 并没有指出如何直接访问 Global Object,但Web浏览器都会将这个全局对象作为 window 对象的一部分加以实现的。所以在全局作用域中声明的所有变量和函数都成为了 window 对象的属性。我听过有些老师说GO==window(我以前也这么想)用起来的时候效果也是如此,但是他们还是有差别的,window 除了扮演 ECMAScript 规定的 Global Object的角色外,还承担了很多别的任务,详见浏览器模型有关内容。
如下代码类似于另一文中的代码

         var a = 123;

         function test() {
            console.log(window.a);
         }
         window.test();
         //输出123

【例】再比如下面代码,百度某年面试题改编,问如何输出?

         console.log(bar());

         function bar() {
            console.log("foo=" + foo);
            foo = 10;
            console.log("foo=" + foo);

            function foo() {}
            var foo = 11;
            console.log("foo=" + foo);
            return foo;
         }
         console.log(window.foo);
         // foo=function foo() {}
         // foo=10
         // foo=11
         // 11
         // ReferenceError: window is not defined

此外,还有一种获取Global对象的方法为

         // 方法1
         var global = function () {
            return this;
         }();

         // 方法2
         document.defaultView

【例】

         var a = 123;
         var global = function () {
            return this;
         }
         var w = global();
         alert(w.a);
         // alert 123

1.4.1. window对象的属性和方法

大量细节详见 MDN_Web/API/Window

2. Math对象

GO下有许多:

  1. Built-in objects
  2. Expressions & operators
  3. Statements & declarations
  4. Functions
  5. Classes
  6. Errors
  7. Misc

详见 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects

Math是其中一个内置对象,Math is a built-in object that has properties and methods for mathematical constants(数学常数) and functions. It’s not a function object.

2.1. Math对象的属性

属性名描述
Math.E自然对数的底数e
Math.LN22的自然对数
Math.LN1010的自然对数
Math.LOG2E以2为底的对数
Math.LOG10E以2为底的对数
Math.PI圆周率Π

等等,其他详见Math#Properties

2.2. Math对象的方法

详见Math#Properties

常用的有

  1. Math.abs()
  2. Math.max()
  3. Math.min()
  4. Math.random()
  5. Math.floor()向下取整
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值