前端JS-Day25
forEach和some的区别:forEach用于遍历数组每一项,遇到return不会终止迭代。some遇到return true会终止迭代,效率更高,一般用于查询数组的唯一项。
map方法:参数和功能与forEach类似,不同点在于map会返回一个新数组且map执行速度更快!
trim方法:去除字符串两端的空格,返回一个新的字符串
对象方法:
Object.keys方法:参数为对象,用于遍历对象,console.log输出为对象的属性(无具体值)。
delete方法:删除对象属性。eg:delete obj.属性
Object.defineProperty方法:参数为:对象,属性名,特性(对象格式)用于修改对象属性。(vue的关键方法)
特性包括:value值,writeable是否可被重写,enumerable是否能被遍历(默认为false且只在使用Object.defineProperty方法时创建的属性才为false,原有属性不会受到影响),configurable为是否能被删除。

当我们需要在对象找方法的时候可以使用console.dir()进行打印。
console.log和console.dir区别:
console.log()可以取代alert()或document.write(),在网页脚本中使用console.log()时,会在浏览器控制台打印出信息console.dir()可以显示一个对象所有的属性和方法。
函数定义:
1.自定义函数:fuction fn(){}
2.函数表达式:let fn = fuction(){}
3.new Function方法: let fn = new Function('参数','函数体')
注意:所有函数都是Function的实例对象,故函数也属于对象,故函数也有原型,故也符合原型链。

函数调用:
<script>
// 普通函数
function fn1() {
console.log('普通函数');
}
fn1();
// 对象方法
let o = {
fn2:function() {
console.log('对象函数');
}
}
o.fn2();
// 构造函数
function Fn3(){};
new Fn3();
// 绑定事件函数
btn.onclick() = function() {};
// 定时器函数
setInterval(function(){}, interval);
// 立即执行函数 自动调用
(function(){})();
</script>
函数内部的this指向:
1.普通函数:指向window
2.对象方法:指向该方法所属对象
3.构造函数:指向实例化对象,原型对象里的方法也指向实例对象
4.绑定事件函数:指向绑定的对象即函数调用者
5.定时器函数:指向window
6.立即执行函数:指向window
改变函数内部的this指向:
1.call方法:
参数:(this对象,传参....)
作用:①调用函数、②改变this指向、③实现继承

2.apply方法:
参数:(this对象,[参数])传参必须是数组形式(伪数组)!
作用:①调用函数、②改变this指向、③借助数学对象实现数组的新方法

apply实现数组的一些方法:
let arr = [1, 2, 3, 5];
let maxV = Math.max.apply(Math, arr);
console.log(maxV); // 输出最大值即5
3.bind方法:不会调用函数,仅进行一个绑定的过程!
参数:(this对象,参数...)
作用:①改变this指向、②返回一个新函数(原函数的拷贝,this已改变)

如果不希望调用函数但又希望改变该函数的this指向,就使用bind方法
例如:对一个按钮实现点击禁用但三秒后又要开启,但如果直接在setTimeout里用this,this指向的是window而不会改变按钮的属性,此时采用的是bind方法,故不会直接去调用定时器内部的函数,所以要在定时器的回调函数外部设置bind方法改变this的指向到调用者btn按钮,这样内部的this指向就变为了btn按钮,便可以设置属性。
<button>123213</button>
<script>
let btn = document.querySelector('button');
btn.onclick = function() {
this.disabled = true;
setTimeout(function(){
// 由于定时器函数内部this指向window故不能直接使用this解放按钮
this.disabled = false;
}.bind(this), 3000);
}
</script>
call、apply、bind总结:
相同:都可以改变函数内部的this的指向。
不同:1.call和apply会直接调用函数,bind不会。2.apply传参是伪数组形式,call和bind为正常传入。
运用场景:call经常做继承。apply与数组有关,实现数组的一些方法。bind实现不调用函数就改变this指向,例如修改定时器的this指向。
严格模式:具有限制性js的变体方式,即在限制性条件下执行js代码。

开启严格模式:'use strict'语句
1.为脚本开启严格模式:


2.为函数开启严格模式:

严格模式中的变化:
1.变量规定:
① 严禁使用未声明的变量。
② 严禁删除已经定义好的变量:delete X是非法的。
2.this指向:
① 正常模式下全局作用域中的this一般指向window,严格模式下全局作用域中this指向undefined。
② 在严格模式下,构造函数不加new就去调用,this指向undefined,给它赋值会报错。
③ 定时器在严格模式下,this仍然指向window。
④ 事件、对象的this仍然指向调用者。
3.函数变化:
① 严格模式下函数中不能有重复名的参数。
② 函数必须声明在顶层,ES6的块级作用域不允许在非函数的代码块中声明函数。即不能在for循环或者if语句内声明函数。
高阶函数:对其他函数进行操作的函数,它接受函数为参数或返回值为函数。
<script>
function fn(a, b) {
a && a();
b && b();
};
fn(function(){
console.log(123);
}, function(){
console.log(456);
})
</script>

闭包closure:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域。
闭包 = 内层函数 + 外层函数的变量。
简单来说就是一个作用域可以访问另外一个函数内部的局部变量。
1.变量作用域:全局变量和局部变量。
① 函数内部可以使用全局变量。
② 函数外部不能使用局部变量。
③ 函数执行完毕,内部局部变量会销毁。
2.闭包作用:封闭数据,延伸了变量的作用范围,外部可以访问函数内部的变量。
function fn() {
let num = 10;
return function () {
console.log(num);
}
}
const f = fn();
f();
// 此时外部可以访问到内部的num值则fn为闭包
闭包运用:实现数据私有
// 需求:输出函数被调用次数
let i = 0;
function fn1() {
i++;
console.log(i);
}
// 旧版实现,i为全局变量,一旦被修改则输出错误。
function fn2() {
let i = 0;
return function() {
i++;
console.log(i);
}
}
// 闭包方式实现,实现数据私有,不会被强制修改!
闭包可能引起内存泄漏!!
立即执行函数+闭包,解决异步问题。
递归函数:函数内部自己调用自己。
递归函数一定要设置退出条件。
利用递归实现遍历对象元素:
<script>
var data = [{
id: 1,
name: '家电',
goods: [{
id: 11,
gname: '电视'
}, {
id: 12,
gname: '洗衣机'
}]
}, {
id: 2,
name: '服饰'
}];
// 利用forEach遍历每一个对象且forEach递归时会自动退出
var o = {};
function getId(json, id) {
json.forEach(function (item) {
if (item.id === id) {
o = item;
} else if (item.goods && item.goods.length > 0) {
o = getId(item.goods, id);
}
});
return o;
}
console.log(getId(data, 1));
console.log(getId(data, 2));
console.log(getId(data, 11));
console.log(getId(data, 12));
</script>
浅拷贝和深拷贝:
浅拷贝:只是拷贝一层,更深层次的对象只拷贝引用即拷贝的是地址。
!!浅拷贝修改值会影响原对象本身的值!!
浅拷贝语法糖:Object.assign(需要拷贝的对象,原对象);
深拷贝:拷贝多层,每一层的对象都会被拷贝。
function deepCopy(newobj, oldobj) {
for (var k in oldobj) {
// 判断简单数据类型还是复杂数据类型
// 1.获取属性值 2.判断数据类型
var item = oldobj[k];
if (item instanceof Array) {
newobj[k] = [];
deepCopy(newobj[k], item);
} else if (item instanceof Object) {
newobj[k] = {};
deepCopy(newobj[k], item);
} else {
newobj[k] = item;
}
}
}

浙公网安备 33010602011771号