您的当前位置:首页正文

前端硬核知识点(四)

2024-12-01 来源:个人技术集锦

1、怎么删除数组指定下标的值?怎么在数组指定下标后插入值?怎么在数组中替换指定下标的值?
let a = [1,2,3,4,5]; a.slice(-1)[0];

a.splice(2,1); // 从下标2开始,删除1个数 。效果:3被删除

a.splice(2,0,‘6’); // 从下标2开始,删除0个数,插入一个字符‘6’。效果:3替换成‘6’

a.splice(2,1,‘red’,‘blue’); // 从下标2开始,删除1个数,插入字符‘red’和‘blue’。效果:3替换成了’red’,‘blue’

2、什么是生成器(generator)?有什么用?

function *fn() {};
or
let fn = function* (); // 箭头函数不能用来声明生成器

生成器实现迭代接口,所以有next()方法,生成器开始是暂停状态即不会执行方法内逻辑,.next()后才执行,返回一个对象,有两个属性:done和value。分别表示生成器状态(返回true或false)和生成器(如上的fn)的return返回的值。

function* fn() {
	console.log('0');
	yield '第一次执行next的返回{done: false, 1}';
	console.log('1');
	yield '第二次执行next的返回{done: false, 2}';
	console.log('2');
	return '第三次执行next的返回{done: true, 3}';
	console.log('3');
}; 
let test = fn();
let test2 = fn();
test.next();
test.next();
test2.next();
// 0
// 1
// 0
// {value: '第一次执行next的返回{done: false, 1}', done: false}
// ----------其它---------
// 循环示例如下,现象:类似连续调用next到done为true;
for (item of test) {
	console.log('生成器循环');
	console.log(item);
}

生成器的主要作用是可以使用yield 来中断逻辑,经过交互再使用next继续逻辑。
生成器内部会区分作用域,生成器对象不会相互影响。
使用场景:例如避免回调地狱等

3、
对象有属性,属性分数据属性和访问器属性,属性有各自的特性,比如[[Writable]],[[Get]],[[Set]],这些特性不能直接访问,但可以通过哪个方法来间接修改?

Object.defineProperty() // 第一个参数:给其添加属性的对象,第二个:属性名称,第三个:描述符对象
// 如:
let book = {
	currentYear: 2017,
	edit: 1,
};
Object.defineProperty(book, 'year', {
	get() {
		return '现在是' + this.currentYear;
	},
	set(newValue) {
		if (newValue > 2017) {
			this.currentYear = newValue;
			this.edit += (newValue - 2017)
		} else {
			this.currentYear = 2017;
		}
	}
})
book.year = 2018;
console.log(book.edit) // 2
console.log(book.currentYear) // 2018
console.log(book.year) // 现在是2018
book.year = 2016;
console.log(book.year) // 现在是2017

4、什么是代理?js怎么创建代理?

// 最简单的定义
let target = {
	id: '1',
};
let handler = {};
let proxy = new Proxy(target, handler) // 第一个参数是目标对象;第二个参数是处理程序对象,是代理嵌入的额外操作
// 复杂一些,给处理程序对象内添加各种破获器
let handler = {
	get(trapTarget, property, receiver) { // 这是get捕获器。参数:目标对象,要查询的属性,代理对象
		return property + ':这是get捕获器内的返回';  // 换成trapTarget[property]即打印返回:1:这是get捕获器内的返回
	}
};
console.log(proxy.id)) // id:这是get捕获器内的返回

5、 什么是纯函数?(如redux的 reducer就需要上纯函数)

const initialState = { value: 0 }
function counterReducer(state = initialState, action) {
  // 检查 reducer 是否关心这个 action
  if (action.type === 'counter/increment') {
    // 如果是,复制 `state`
    return {
      ...state,
      // 使用新值更新 state 副本
      value: state.value + 1
    }
  }
  // 返回原来的 state 不变
  return state
}

6、纯函数的好处?

var memoize = function(f) {
  var cache = {};
  return function() {
    var arg_str = JSON.stringify(arguments);
    cache[arg_str] = cache[arg_str] || f.apply(f, arguments);
    return cache[arg_str];
}; };

var squareNumber  = memoize(function(x){ return x*x; });
squareNumber(4);
//=> 16
squareNumber(4);
//=> 16
squareNumber(5);
//=> 25
squareNumber(5);
//=> 25

纯函数总能够根据输入来做缓存。实现缓存的一种典型方式是 memoize 技术

Tip: 函数如果有引用外部的的变量,为了纯函数化,需要处理这个变量,讲变量设定为不可变。如下对象,不可新增删除修改属性

var immutableState = Object.freeze({
  minimum: 21
});

7、什么叫 副作用?

- 改变/修改输入参数,如:入参是一个对象,方法内为这个对象新增一个属性,再返回这个对象
- 修改函数外的任何其他状态,如全局变量,document.(anything)或window.(anything)
- 进行 API 调用 如:fetch('/users')
- console.log()
- Math.random()

8、js哪些方法会修改原数组?React里的概念,即是可变的(mutability)

push(在末尾添加一个项目)
pop(从末尾删除一个项目)
shift (从头删除一个项目)
unshift(在开头添加一个项目)
sort(排序-可自定义比较规则)
reverse 逆序
splice 处理原数组(删除,替换)
显示全文