常见问题
- 箭头函数与普通函数(function)的区别是什么?
- 构造函数(function)可以使用New生成实例,那么箭头函数也可以吗?为什么?
箭头函数与普通函数的区别:
- 箭头函数在语法上比普通函数更为简洁(ES6语法形参的默认值与剩余参数都适用于箭头函数和普通函数)
- 箭头函数没有自己的this,他里面的this是继承函数所处上下文,没有继承函数就是window(用call,applay等任何方法都无法改变箭头函数的this的指向)
- 普通函数的this指的是函数的调用者
- 箭头函数没有arguments(类数组),只能基于…arg获取参数的集合(数组)
- 箭头函数不能使用New生成实例(因为:箭头函数没有this并且没有prototype属性)
/*
箭头函数没有arguments(类数组),只能基于...arg获取参数的集合(数组)
let arr = [10,20,30]
let fn1 = function(){
console.log(arguments) // 类数组
}
fn1(arr)
let fn2 = function(...arg){
console.log(arg) // 数组
}
fn2(arr); */
/*
箭头函数不能使用New生成实例(因为:箭头函数没有this并且没有prototype属性)
function Fn(name){
this.name = name
}
Fn.prototype.add = function() {}
let fn = new Fn()
let Fn2 = (name) => {
this.name = name;
}
console.dir(Fn2); // 查看对象所有属性和方法
let fn2 = new Fn2(); //Fn2 is not a constructor */
/*
箭头函数在语法上比普通函数更为简洁
let fn1 = function(x) {
return function(y) {
return x + y
}
}
let fn2 = x => y => x + y */
/*
箭头函数没有自己的this,他里面的this是继承函数所处上下文中的this
let obj = {"name":"xiaofang"}
function fn1() {
console.log(this)
}
fn1() // WINDOW
fn1.call(obj) // {name:"xiaofang"}
let fn2 = () => {
console.log(this)
}
fn2() // WINDOW
fn2.call(obj); // WINDOW */
/* document.body.onclick = () => {
// this 指的是WIDNOW 不是调用者
} */
/* document.body.onclick = function() {
// this 指的是调用者 body
// SORT 方法里面的this是arr
// 但是这个回调函数不是 回调函数是把一个函数当做一个参数传给别人执行
//sort只是帮忙把回调函数执行了,没有手动改变回调函数的this,回调函数里面的this还是指向的WINDOW
// Array.sort(function(a,b){
// // this:WINDOW
// return a + b
// })
// 换为箭头函数 就是继承函数上下文中的this了
Array.sort((a,b) => {
// this:BODY 继承上面的函数
return a + b
})
}; */
// 回调函数:把一个函数B作为实参传递给另外一个函数A,
//函数A在执行的时候,可以把传递进来的函数B去执行(执行N次,可传值,可改this,可返回值)
/* function each(arr,callback) {
for(let i = 0;i<arr.length;i++) {
let item = arr[i];
index = i
// callback(item,index)
// callback.call(arr,item, index);
// 接受回调函数返回结果 结果返回结果做判断
let flag = callback.call(arr, item, index);
if (flag === false) {
break;
}
}
}
each([10,20,30],function(item,index){
// console.log(item , index)
console.log(this)
if(index > 0) {
return false;
}
return true
}) */
/* //思考题1:
// :问题
let arr = [10,20,30,"Aa",40];
let obj = {}
let newArr = arr.each(function(item,index){
// 如果没有obj 则this为WINDOW 有则为obj
if(isNaN(item)){
return false
// 当为false时,跳出循环
}
return item * 10
},obj)
console.log(newArr) //[100, 200, 300, "Aa", 40]
// newArr = [100,200,300,"Aa",40]
// :答案
~function(){
function each(callback,obj) {
let arr = this;
let newArr = []
let breakIndex = null
for(let i = 0;i<arr.length;i++) {
let item = arr[i]
let index = i
let respValue = obj ? callback.call(obj,item,index) : callback(item,index);
if(respValue === false) {
breakIndex = index
break
} else {
newArr.push(respValue)
}
}
if(breakIndex) {
for(let i = breakIndex;i<arr.length;i++) {
newArr.push(arr[i]);
}
}
return newArr
}
Array.prototype.each = each
}()
*/
// 思考题2 重写repalce 就是把字符以要替换的文字(split)分隔为数组,在把新文字连接(join)为字符串
~(function() {
function replace(reg, callback) {
let str = this;
let result = "";
while ((result = reg.exec(str)) !== null) {
let newReplaceStr = callback(result);
// result 返回的是一个数组
// reg.lastIndex 是查找到的str最后一个下标值
console.log(result, reg.lastIndex);
let newArr = str.split(result[0]);
console.log(newArr.join(newReplaceStr));
return newArr.join(newReplaceStr)
}
}
String.prototype.replace = replace;
})();
let str = "zhufeng2019zhufeng2029";
let newStr = str.replace(/zhufeng/g, function(...arg) {
console.log(arg)
// arg 中存储了每一次大正则匹配的信息和小分组匹配的信息
return "@"; // 返回是什么就把当前正则匹配的内容替换为什么
});
console.log(str.replace(/zhu/g, function(...arg) {
return "123";
}))