首页 > 语言 > JavaScript > 正文

一些你可能不熟悉的JS知识点总结

2024-05-06 15:41:39
字体:
来源:转载
供稿:网友

 暂时性死区

只要块级作用域存在let命令,它所声明的变量就“绑定”这个区域,不再受外部的影响。这么说可能有些抽象,举个例子:

var temp = 123;if(true) { console.log(temp); let temp;}

 结果:

> ReferenceError: temp is not defined

 在代码块内,使用let声明变量之前,该变量都是不可用的。在语法上,称为“暂时性死区”。(temporal dead zone)

ES6规定暂时性死区和let、const语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。

call和apply方法

这两个方法都可以改变一个函数的上下文对象,只是接受参数的方式不一样。
call接收的是逗号分隔的参数。

apply接收的是参数列表。

相信你肯定看到过这样的代码:

var arr = [1, 2, 3];var max = Function.prototype.apply.call(Math.max, null, arr);console.log(max); // 3

那么对这段代码怎么理解呢?

1.将Function.prototype.apply看成一个整体

(Function.prototype.apply).call(Math.max, null, arr)

2.func.call(context, args)可以转化为context.func(args)

所以代码被转换为:

Math.max.apply(undefined, arr)

基本上到这一步已经没必要去解释了。

那么你有没有试过将call和apply互换位置呢?

var arr = [1, 2, 3];var max = Function.prototype.call.apply(Math.max, null, arr);console.log(max); // -Infinity

为什么的它的输出结果为-Infinity呢?

因为apply的第二参数必须为数组,这里并不是,所以参数不能正确的传递给call函数。
根据func.apply(context, args)可以转化为context.func(args)。所以被转化成了Math.max.call(), 直接调用则会输出-Infinity。

如果想要正确调用,则应这样书写:

var arr = [1, 2, 3];var max = Function.prototype.call.apply(Math.max, arr);console.log(max); // 3

为了巩固以上内容,且看一个面试题:

var a = Function.prototype.call.apply(function(a){return a;}, [0,4,3]);alert(a); 

分析弹出的a值为多少?

// 将call方法看成一个整体(Function.prototype.call).apply(function(a){return a;}, [0,4,3]);// func.apply(context, args)可以转化为context.func(...args)(function(a){return a;}).call(0, 4, 3);// 所以结果很明显,输出4

Proxy对象

作用:用来自定义对象中的操作。

let p = new Proxy(target, handler)

target 代表需要添加代理的对象,handler 用来自定义对象中的操作,比如可以用来自定义 set 或者 get 函数。

且看一个的小栗子:

// onChange 即要进行的监听操作var watch = (object, onChange) => { const handler = {  // 如果属性对应的值为对象,则返回一个新的Proxy对象  get(target, property, receiver) {   try {    return new Proxy(target[property], handler);   } catch (err) {    return Reflect.get(target, property, receiver);   }  },  // 定义或修改对象属性  defineProperty(target, property, descriptor) {   onChange('define',property);   return Reflect.defineProperty(target, property, descriptor);  },  // 删除对象属性  deleteProperty(target, property) {   onChange('delete',property);   return Reflect.deleteProperty(target, property);  } }; return new Proxy(object, handler);};// 测试对象var obj = { name: 'bjw', age: 22, child: [1, 2, 3]}// 对象代理var p = watch(obj1, (type, property) => {  console.log(`类型:${type}, 修改的属性:${property}`)});p.name = 'qwe' 类型:define, 修改的属性:name "qwe"p.child Proxy {0: 1, 1: 2, 2: 3, length: 3} p.child.push(4) 类型:define, 修改的属性:3 类型:define, 修改的属性:length 4p.child.length = 2 类型:define, 修改的属性:length 2p.child Proxy {0: 1, 1: 2, length: 2}            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选