js一些有用但不常用到的语法解析

NAN,isNAN

NAN属于number类型,是用于特殊引用的非数字字符

<body>
​
    <script type="text/javascript">
        console.log(isNaN(123))//false
        console.log(isNaN(NaN))//true
        console.log(isNaN("123"))//false
​
        console.log(isNaN("123 "))//false
​
        console.log(isNaN("asd"))//true
    </script>
</body>

arguments、caller 和 callee

arguments:

在函数调用时, 会自动在该函数内部生成一个名为 arguments的隐藏对象。 该对象类似于数组, 但又不是数组。可以使用[]操作符获取函数调用时传递的实参。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Arguments Test</title>
</head>
<body>
<script>
function testArg()
{
    alert("real parameter count: "+arguments.length);
    for(var i = 0; i < arguments.length; i++)
    {
        alert(arguments[i]);
    }
}
 
 
testArg(11);  //count: 1    
testArg('hello','world');  // count: 2  
</script>
</body>
</html>

看上去很简单。 需要注意的是 argument 保存的实参的信息。

上面有说, arguments 不是一个数组,何以见得? 执行以下部分就可以知道了

(function () {
    alert(arguments instanceof Array); // false
    alert(typeof(arguments)); // object
})();

只有函数被调用时,arguments对象才会创建,未调用时其值为null:
alert(new Function().arguments);//return null

arguments 的完整语法如下:
[function.]arguments[n]
参数function :选项。当前正在执行的 Function 对象的名字。 n :选项。要传递给 Function 对象的从0开始的参数值索引。

caller

在函数调用另一个函数时,被调用函数会自动生成一个caller属性,指向调用它的函数对象.如果该函数当前违背调用,或并非被其他函数调用,啧caller为null

​
<script>
function testCaller() {
    var caller = testCaller.caller;
    alert(caller);
}
 
function aCaller() {
    testCaller();
}
 
aCaller();

callee

当函数被调用时,它的arguments.callee对象就会指向自身,也就是一个对自己的引用

由于arguments在函数调用时才有效,因此arguments.calee在函数未调用时是不存在的()

apply和call

js中的每一个function都有一个apply和call方法,他们的语法分别为

function.apply(thisObj[,argArray])
function.call(thisObj[,arg1[,arg2[,...argN]]])

基本用法

function add(a,b){
  return a+b;  
}
function sub(a,b){
  return a-b;  
}
var a1 = add.apply(sub,[4,2]);  //sub调用add的方法
var a2 = sub.apply(add,[4,2]);
alert(a1);  //6     
alert(a2);  //2
​
/*call的用法*/
var a1 = add.call(sub,4,2);

各自定义

apply:调用一个对象的一个方法,用另一个对象替换当前对象,例如B.apply(A,arguments)即A对象应用B对象的方法

call:调用一个对象的一个方法,用另一个对替换当前对象,入B.call(A,args1,args2)即A对象调用B对象方法

共同之处

都可以用来提另一个对象调用一个方法,讲一个函数对象上下文从初始的上下文变为由thisObj指定的新对象

不同之处

apply:最多只能有俩个参数--新this对象和一个数组argArray.如果给该方法传递多个参数,则把参数都写进数组里面,当然即使只有一个参数,也要写进数组里.如果argArray不是一个有效的数组或arguments对象,那么将导致一个typeError.如果没有提供ArgArray和thisObj任何一个采纳数,那么Global对象江北用作thisOBJ并且无法被传递任何参数

call:它可以接受多个参数,第一个参数与apply一样,后面则是一串参数列表.这个方法主要用在js对象方法相互调用的时候,使当前this实例指针保持一致,或者在特殊情况下需要改变this指针.如果没有提供thisOBJ参数,那么Global对象被用作thisObj

实际上apply和calll的功能是一样的,只是传入的参数列表形式不同

instanceof和typeof

用于南侧构造函数的prototype属性是否出现在某个实例对象的原型链上

语法:

object instanceof constructor

typeof()

返回类型

用法()

​
typeof(10);
typeof(NaN);
//NaN在JavaScript中代表的是特殊非数字值,它本身是一个数字类型。
typeof(Infinity);
1.String<br/><br/>2.Number<br/><br/>3.Boolean<br/><br/>4.Object<br/><br/>5.Function<br/><br/>6.undefined
## es6新语法 ### yield yield是es6的新关键字 ,使生成函数执行暂停,yield关键字后面的表达是值返回给生成器的调用者.它可以被认为是一个基于生成器的版本的return关键字. yield关键字返回的实际是一个iteratorresult(迭代器)对象,它有俩个属性,value和done,分别代表返回值和是否完成 yield无法单独工作,需要配合generatir(生成器)的其他函数,如next,懒汉式操作,展现强大的主动控制特性。 > generator生成器是es6标准引入的新的数据类型.一个genertator看上去像一个函数,但可以返回多次. 与函数的不同之处是,generrator由fnction定义(注意多出的号),并且,除了return语句,还可以用yield返回多次
 function* myYield(list) {<br/>    for (let i = 0; i < list.length; i++) {<br/>      yield list[i]<br/>    }<br/>  }<br/>  const numList = myYield([1,4,8])<br/>  console.log(numList.next())//{done: false,value: 1}<br/>  console.log(numList.next())//{done: false,value: 4}<br/>  console.log(numList.next())//{done: false,value: 8}<br/>  console.log(numList.next())//{done: true,value: undefined}
遍历迭代器
  for (let n = numList.next(); !n.done; n=numList.next()) {<br/>    console.log(n.value)<br/>  }
简单的概括,每次执行next(),都会执行一个yield返回的值 yield可以用来加强控制懒汉式加载 每次调用返回俩个值,分别是value和done,代表迭代结果是否完成 next是迭代器对象,传参可缺省,默认调用函数 1. yield并不能直接生产值,而是产生一个等待输出的函数 2. 除IE外,其他所有浏览器均可兼容 3. 某个函数包含了yield,意味着这个函数是一个Generator 4. 如果yield在其他表达式中,需要用()单独括起来 5. yield表达式 本身没有返回值,其实是由next返回的 6. next可以无线调用,单循环完成后就返回undefined ### Symbol es6引入了一种新的原始数据类型Symbol,表示独一无二的的值,最打的用法是来定义对象的唯一属性名 ES数据类型除了Number,String,Boolean,Object,null和undefined,还新增了Symbol Symbol函数不能用new命令,因为Symbol 是原始数据类型,表示对象.可以接受一个字符串作为参数,为新创建的Symbol 提供描述,用来显示在控制台或者作为字符串时候使用,便于区分
let sy = Symbol("KK");<br/>console.log(sy);   // Symbol(KK)<br/>typeof(sy);        // "symbol"<br/> <br/>// 相同参数 Symbol() 返回的值不相等<br/>let sy1 = Symbol("KK"); <br/>console.log(sy === sy1)       // false
#### 使用场景 作为属性名 由于个symbol的值都是不相等的,所以Symbol作为对象的属性名可保证属性不重名
let sy = Symbol("key1");<br/> <br/>// 写法1<br/>let syObject = {};<br/>syObject[sy] = "kk";<br/>console.log(syObject);    // {Symbol(key1): "kk"}<br/>// 写法2<br/>let syObject = {<br/>  [sy]: "kk"<br/>};<br/>console.log(syObject);    // {Symbol(key1): "kk"}<br/> <br/>// 写法3<br/>let syObject = {};<br/>Object.defineProperty(syObject, sy, {value: "kk"});<br/>console.log(syObject);   // {Symbol(key1): "kk"}
### Symbol.for() Symbol.for() 类似单例模式,首先会在全局搜索被登记的 Symbol 中是否有该字符串参数作为名称的 Symbol 值,如果有即返回该 Symbol 值,若没有则新建并返回一个以该字符串参数为名称的 Symbol 值,并登记在全局环境中供搜索。
let yellow = Symbol("Yellow");<br/>let yellow1 = Symbol.for("Yellow");<br/>yellow === yellow1;      // false<br/> <br/>let yellow2 = Symbol.for("Yellow");<br/>yellow1 === yellow2;     // true
### Symbol.keyFor() Symbol.keyFor() 返回一个已登记的 Symbol 类型值的 key ,用来检测该字符串参数作为名称的 Symbol 值是否已被登记。
let yellow1 = Symbol.for("Yellow");<br/>Symbol.keyFor(yellow1);    // "Yellow"
### map和set map对象保存键值对,任何值(对象或原始值)都可以作为一个键或一个值 #### Maps和Object区别 * 一个Object的键只能是字符串或symbols,但一个map的键可以是任意值 * Map中的键值是有序的(FIFO原则),而添加到对象中的键则不是 * Map的键值对个数可以从size获取,Object的键值对个数只能手动计算 * Object都有自己的原型原型链上的键名有可能和自己在对象上的设置的键名产生冲突 key是字符串
var myMap = new Map();<br/>var keyString = "a string"; <br/> <br/>myMap.set(keyString, "和键'a string'关联的值");<br/> <br/>myMap.get(keyString);    // "和键'a string'关联的值"<br/>myMap.get("a string");   // "和键'a string'关联的值"<br/>                         // 因为 keyString === 'a string'
key是对象
var myMap = new Map();<br/>var keyObj = {}, <br/> <br/>myMap.set(keyObj, "和键 keyObj 关联的值");<br/>myMap.get(keyObj); // "和键 keyObj 关联的值"<br/>myMap.get({}); // undefined, 因为 keyObj !== {}
key是函数
var myMap = new Map();<br/>var keyFunc = function () {}, // 函数<br/> <br/>myMap.set(keyFunc, "和键 keyFunc 关联的值");<br/> <br/>myMap.get(keyFunc); // "和键 keyFunc 关联的值"<br/>myMap.get(function() {}) // undefined, 因为 keyFunc !== function () {}
key是NAN
var myMap = new Map();<br/>myMap.set(NaN, "not a number");<br/> <br/>myMap.get(NaN); // "not a number"<br/> <br/>var otherNaN = Number("foo");<br/>myMap.get(otherNaN); // "not a number"
虽然 NaN 和任何值甚至和自己都不相等(NaN !== NaN 返回true),NaN作为Map的键来说是没有区别的。 map的迭代 for...of
var myMap = new Map();<br/>myMap.set(0, "zero");<br/>myMap.set(1, "one");<br/> <br/>// 将会显示两个 log。 一个是 "0 = zero" 另一个是 "1 = one"<br/>for (var [key, value] of myMap) {<br/>  console.log(key + " = " + value);<br/>}<br/>for (var [key, value] of myMap.entries()) {<br/>  console.log(key + " = " + value);<br/>}<br/>/ 这个 entries 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的 [key, value] 数组。 /<br/> <br/>// 将会显示两个log。 一个是 "0" 另一个是 "1"<br/>for (var key of myMap.keys()) {<br/>  console.log(key);<br/>}<br/>/ 这个 keys 方法返回一个新的 Iterator 对象, 它按插入顺序包含了 Map 对象中每个元素的键。 /<br/> <br/>// 将会显示两个log。 一个是 "zero" 另一个是 "one"<br/>for (var value of myMap.values()) {<br/>  console.log(value);<br/>}<br/>/ 这个 values 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的值。 /
forEach()
var myMap = new Map();<br/>myMap.set(0, "zero");<br/>myMap.set(1, "one");<br/> <br/>// 将会显示两个 logs。 一个是 "0 = zero" 另一个是 "1 = one"<br/>myMap.forEach(function(value, key) {<br/>  console.log(key + " = " + value);<br/>}, myMap)
#### set对象 set对象允许存储任何类型的唯一值,无论是原始值或者是对象引用 set中的特殊值 * +0 与 -0 在存储判断唯一性的时候是恒等的,所以不重复; * undefined 与 undefined 是恒等的,所以不重复; * NaN 与 NaN 是不恒等的,但是在 Set 中只能存一个,不重复。
let mySet = new Set();<br/> <br/>mySet.add(1); // Set(1) {1}<br/>mySet.add(5); // Set(2) {1, 5}<br/>mySet.add(5); // Set(2) {1, 5} 这里体现了值的唯一性<br/>mySet.add("some text"); <br/>// Set(3) {1, 5, "some text"} 这里体现了类型的多样性<br/>var o = {a: 1, b: 2}; <br/>mySet.add(o);<br/>mySet.add({a: 1, b: 2}); <br/>// Set(5) {1, 5, "some text", {…}, {…}} <br/>// 这里体现了对象之间引用不同不恒等,即使值相同,Set 也能存储
类型转换
// Array 转 Set<br/>var mySet = new Set(["value1", "value2", "value3"]);<br/>// 用...操作符,将 Set 转 Array<br/>var myArray = [...mySet];<br/>String<br/>// String 转 Set<br/>var mySet = new Set('hello');  // Set(4) {"h", "e", "l", "o"}<br/>// 注:Set 中 toString 方法是不能将 Set 转换成 String
### Reflect 与 Proxy proxy与reflect是ES6为了操作对象引入的API Proxy可以对目标对象的读取函数调用等操作进行拦截,任何进行处理,它不直接操作对象,而是像代理模式,通过对象的代理对象进行操作,在进行这些操作时,1可以添加一些需要的额外操作 Reflect就可以用于获取目标对象的行为,它与Object类似,但是更容易读,未操作对象提供了一种更优雅的方式.他的方法a与proxy是对应的 #### proxy 一个 Proxy 对象由两个部分组成: target 、 handler 。在通过 Proxy 构造函数生成实例对象时,需要提供这两个参数。 target 即目标对象, handler 是一个对象,声明了代理 target 的指定行为。
let target = {<br/>    name: 'Tom',<br/>    age: 24<br/>}<br/>let handler = {<br/>    get: function(target, key) {<br/>        console.log('getting '+key);<br/>        return target[key]; // 不是target.key<br/>    },<br/>    set: function(target, key, value) {<br/>        console.log('setting '+key);<br/>        target[key] = value;<br/>    }<br/>}<br/>let proxy = new Proxy(target, handler)<br/>proxy.name     // 实际执行 handler.get<br/>proxy.age = 25 // 实际执行 handler.set<br/>// getting name<br/>// setting age<br/>// 25<br/> <br/>// target 可以为空对象<br/>let targetEpt = {}<br/>let proxyEpt = new Proxy(targetEpt, handler)<br/>// 调用 get 方法,此时目标对象为空,没有 name 属性<br/>proxyEpt.name // getting name<br/>// 调用 set 方法,向目标对象中添加了 name 属性<br/>proxyEpt.name = 'Tom'<br/>// setting name<br/>// "Tom"<br/>// 再次调用 get ,此时已经存在 name 属性<br/>proxyEpt.name<br/>// getting name<br/>// "Tom"<br/> <br/>// 通过构造函数新建实例时其实是对目标对象进行了浅拷贝,因此目标对象与代理对象会互相<br/>// 影响<br/>targetEpt<br/>// {name: "Tom"}<br/> <br/>// handler 对象也可以为空,相当于不设置拦截操作,直接访问目标对象<br/>let targetEmpty = {}<br/>let proxyEmpty = new Proxy(targetEmpty,{})<br/>proxyEmpty.name = "Tom"<br/>targetEmpty // {name: "Tom"}
#### Reflect ES6中将Object的一些明显属于语言内部的方法移植到了Reflect对象上(当前某些方法会同时存在于Object和Reflect对象上),未来的新方法只会部署在Reflect对象上 Reflect对象对某些方法的返回结果进行了修改使其更合理 reflect对象使用函数的方式实现了Object的命令式操作
Reflect.get(target, name, receiver)<br/><br/>let exam = {<br/>    name: "Tom",<br/>    age: 24,<br/>    get info(){<br/>        return this.name + this.age;<br/>    }<br/>}<br/>Reflect.get(exam, 'name'); // "Tom"<br/> <br/>// 当 target 对象中存在 name 属性的 getter 方法, getter 方法的 this 会绑定 // receiver<br/>let receiver = {<br/>    name: "Jerry",<br/>    age: 20<br/>}<br/>Reflect.get(exam, 'info', receiver); // Jerry20<br/> <br/>// 当 name 为不存在于 target 对象的属性时,返回 undefined<br/>Reflect.get(exam, 'birth'); // undefined<br/> <br/>// 当 target 不是对象时,会报错<br/>Reflect.get(1, 'name'); // TypeError
将 target 的 name 属性设置为 value。返回值为 boolean ,true 表示修改成功,false 表示失败。当 target 为不存在的对象时,会报错。
Reflect.set(target, name, value, receiver)<br/><br/>let exam = {<br/>    name: "Tom",<br/>    age: 24,<br/>    set info(value){<br/>        return this.age = value;<br/>    }<br/>}<br/>exam.age; // 24<br/>Reflect.set(exam, 'age', 25); // true<br/>exam.age; // 25<br/> <br/>// value 为空时会将 name 属性清除<br/>Reflect.set(exam, 'age', ); // true<br/>exam.age; // undefined<br/> <br/>// 当 target 对象中存在 name 属性 setter 方法时,setter 方法中的 this 会绑定 // receiver , 所以修改的实际上是 receiver 的属性,<br/>let receiver = {<br/>    age: 18<br/>}<br/>Reflect.set(exam, 'info', 1, receiver); // true<br/>receiver.age; // 1<br/> <br/>let receiver1 = {<br/>    name: 'oppps'<br/>}<br/>Reflect.set(exam, 'info', 1, receiver1);<br/>receiver1.age; // 1
### es7 async async是es7才有的关键字和,Promise,Generator有很大关联的
async function name([param[, param[, ... param]]]) { statements }
* name 函数名称 * param:要传递给函数的参数的名称 * statements:函数体语句 返回值 async函数返回一个Promise对象,可以使用then方法添加回调函数
async function helloAsync(){<br/>    return "helloAsync";<br/>  }<br/>  <br/>console.log(helloAsync())  // Promise {<resolved>: "helloAsync"}<br/> <br/>helloAsync().then(v=>{<br/>   console.log(v);         // helloAsync<br/>})
async函数中可能会有await表达式,async函数执行时,如果遇到await就会先暂停执行等到出发的异步操作完成后,恢复async函数的执行并发挥解析值 await关键字尽在async function中有效.如果async funciton哈朱提外使用await,只会得到一个语法错误
function testAwait(){
   return new Promise((resolve) => {
       setTimeout(function(){
          console.log("testAwait");
          resolve();
       }, 1000);
   });
}
 
async function helloAsync(){
   await testAwait();
   console.log("helloAsync");
 }
helloAsync();

await

await操作符用于等待一个promise对象,它只能在异步函数async function内部使用

语法

[return_value] = await expression;
  • expression: 一个 Promise 对象或者任何要等待的值。

返回值

返回promise对象的处理结果.如果等待的不是promise对象,则返回该值本身

如果Promise被传递给一个awiat操作符,await等待 Promise 正常处理完成并返回其处理结果。

function testAwait (x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}
 
async function helloAsync() {
  var x = await testAwait ("hello world");
  console.log(x); 
}
helloAsync ();
// hello world

正常情况下,await 命令后面是一个 Promise 对象,它也可以跟其他值,如字符串,布尔值,数值以及普通函数。

function testAwait(){
   console.log("testAwait");
}
async function helloAsync(){
   await testAwait();
   console.log("helloAsync");
}
helloAsync();
// testAwait
// helloAsync

await针对所跟不同表达式的处理方式:

  • Promise 对象:await 会暂停执行,等待 Promise 对象 resolve,然后恢复 async 函数的执行并返回解析值。
  • 非 Promise 对象:直接返回对应的值。
Last modification:April 19, 2022
如果觉得我的文章对你有用,请随意赞赏