JS进阶学习之ES5-ES6
ES5补充拓展
20200429
ECMA介绍
ECMA (欧洲计算机制造商协会)
这个组织的目标是评估、开发和认可计算机标准
ECMA 发布 262 号标准文件(ECMA-262),规定了浏览器脚本语言的标准,并将这种语言称为 ECMAScript
ECMAScript5简介
ECMAScript5, 就是ECMAScript的第五代标准, 也加ES5, 或者叫ESMAScript2009(2009年发布)
ECMAScript规定你JavaScript怎么用, 就得怎么用, 所以ECMAScript是标准, JavaScript是具体的实现(比如没有class关键字啊等等)
严格模式
JavaScript 严格模式, 即在严格的条件下运行
原因:
* 消除 JavaScript 语法的一些不合理、不严谨之处,减少一些怪异行为
* 消除代码运行的一些不安全之处,保证代码运行的安全
* 提高编译器效率,增加运行速度
* 为未来新版本的 JavaScript 做好铺垫
使用:
将”use strict”放在脚本文件的第一行,则整个脚本都将以”严格模式”运行。(如果浏览器不支持, 就会被当成普通字符串, 也没有任何的副作用)
常用规则(特点):
1. 声明定义变量必须用 var
2. 禁止函数中的 this 指向Window
3. eval拥有独立作用域
//==========示例=============
"use strict" // 在第一行写上这个声明, 代表当前代码是严格模式
// 开启严格模式, 变量必须用var 声明
// a = 10;
var a = 10;
console.log(a);
// 禁止this指向 window
// this指向函数的调用者
function fn(){
console.log(this);// 非严格模式window, 严格模式undefined
}
fn();
//eval() 把字符串当作js代码来执行
// 开启严格模式, eval有独立的作用域, 所以不会影响外部
var b = 99;
eval("var b = 33; console.log(b)");
console.log(b); // 非严格模式下: 55 严格模式下: 99
var a = '{"a":10,"b":20}';
eval('('+a+')');
console.log(a);
// 因为eval小括号里的字符串是代码 {} 被当做了代码块, 并不是对象的{}
// 所以 相当于 你直接写了 a: 10 报错了.
// 套个小括号就好了
JSON
注意:
不要把JavaScript里的对象和json数据弄混了 (虽然都是{}大括号, 但json字符串是一种数据格式, 而且必须和只能用双引号)
//=========示例=============
// Ajax请求回来的数据,都是字符串类型
var json = '{"user":"小王","age":18,"class":true}';
//1 JSON.parse() 将json字符串数据-->js对象/数组
var obj = JSON.parse(json);
console.log(obj);
//2 JSON.stringify() js对象/数组-->json字符串数据
var obj2 = {
user:'小代',
'age':18,
"sex":"男"
}
console.log(obj2);
console.log(JSON.stringify(obj2));
// json字符串数据必须使用双引号包裹,包括 key
// js对象,key 可以用引号包裹,也可以不包裹
常用方法:
方法名 | 参数 | 返回值 | 备注 |
---|---|---|---|
JSON.parse() | json字符串 | JavaScript数据(对象/数组) | 一般用在Ajax请求后, 把json字符串转成 JavaScript数据 |
JSON.stringify() | Javascript数据(对象/数组) | json字符串 | 把数据格式化json字符串 |
Object
Object.assign()
作用: 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。(参数1, 即是目标对象)
//========示例==========
// 1 Object.assign() 用于合并对象
var obj1 = {
name:'dyh',
age:18
}
var obj2 ={
sex:'男'
}
//合并对象 先创建个空对象
// 原始方法合并对象
var newobj = {};
//通过for in
for(var key in obj1){
newobj[key] = obj1[key];
}
for(var key in obj2){
newobj[key] = obj2[key];
}
console.log(newobj);
// 通过方法合并
// Object.assign(目标对象,待合并对象1,待合并对象2...)
// 返回值 目标对象 重复的内容会覆盖
var kk = Object.assign({},obj1,obj2,newobj);
console.log(kk);
Object.create() --- 主要用在新建对象
作用 : 以指定对象为原型创建新的对象,并为新的对象指定新的属性 , 并对属性进行描述。
//==========示例==============
let obj = {name: 'dyh'};
let newObj = Object.create(obj, {
sex : {
value : '男',
writable : true,
configurable: true,
enumerable: true
} // 每个属性可以进行配置设置
})
newobj.sex = '女';
delete newobj.age;
console.log(newobj);
newobj.__proto__.name = '单引号';
for (var key in newobj) {
console.log(key, '----', newobj[key]);
}
value : 指定值
writable : 标识当前属性值是否是可修改的, 默认为false (不可修改)
configurable: 标识当前属性是否可以被删除 默认为false (不可删除)
enumerable: 标识当前属性是否能用for in 枚举 默认为false (不可遍历)
注意:
1. 参数1不会受影响
2. 此方法是在参数1为基准, 额外添加新的属性
3. 可以对添加的新属性, 进行一些权限的控制
4. 基准对象是扩展在新建的对象的__proto__原型属性上
Object.defineProperty() --- 主要用在 新增属性/监听属性
作用: 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性。
set函数: 触发属性的赋值动作, 会触发此函数, 传入一个要赋予的值作为形参
get函数: 触发属性的取值动作, 会触发此函数, 需要return一个结果
使用场景: 可以对 对象age属性, 在set函数中判断合法性
//=======示例===========
// Object.defineProperty()
// 作用:可以给现有对象,添加一个属性 并且控制全选 / 对现有属性添加控制权限
var obj = {
name: 'dyh',
age: 18
}
// 1 给现有对象添加 新属性 并添加控制权限
// Object.defineProperty(目标对象,参数1:新增key名,参数2:新增key名2)
Object.defineProperty(obj, "sex", {
value: '男',
writable: false, // (默认不写false), false此属性值, 不可以被更改
configurable: false, // false, 不可以被删除
enumerable: false, // false, 不可以被for...in遍历
});
obj.sex = '女';
console.log(obj);
//2 给现有对象添加新属性 / 对象现有属性 并进行权限控制
// 方法:set(),get() 赋值 / 取值
var obj2 = {
name:'dyh',
age:18
}
var age_;// 为了防止set内 使用obj.age = val,
Object.defineProperty(obj2,'age',{// 重写age属性的赋值 和 取值的 过程
set(val){ // 对age属性, 赋值时会触发set方法
age_ = val;
console.log('age被从新赋值');
},
get(){// 对age属性, 取值时会触发get方法
console.log('age 被取值了');
return age_;
}
})
obj2.age = 22;
console.log(obj2.age);
//==========应用场景===============
var obj = {
age: 18
}
var age_;
Object.defineProperty(obj, 'age', {
set(val){
// 判断val值的类型不是数字类型 || val小于0 || val大于150
if (typeof val !== "number" || val < 0 || val > 150) {
console.error("年龄非法了");
} else {
age_ = val;
}
},
get(){
return age_;
}
})
// 需求: 外部使用obj对象时, 给age属性赋值的时候, 要在内部做一些监测判断
obj.age = "给你个年龄";
console.log(obj.age);
Object.defineProperties()
//==========示例=============
Object.defineProperties(obj, {
'property1': {
value: true,
writable: true,
set(val){},
get(){}
},
'property2': {
value: 'Hello',
writable: false
}
})
此方法作用同上, 只不过可以同时监听多个属性
//===========示例=================
// Object.defineProperties() 和 Object.defineProperty()使用是差不多的
let obj = {
userName: "小代"
}
Object.defineProperties(obj, {
age: {
value: 18,
writable: true
},
address: {
value: "安徽" // 其他属性同Object.create()里的权限属性
}
})
// value+writable 和 set/get不要同时写
Array
对象调用的方法 | 作用 | 返回值 |
---|---|---|
array.forEach(function(value, index, array){}) | 遍历 | 无 |
array.map(function(value, index, array){}) | 遍历&返回 | 新数组 |
array.filter(function(value, index, array){}) | 过滤&返回 | 新数组 |
array.reduce(function(sum, value, index, array) {}, 0) | 遍历&累计 | 累计结果 |
注意:
1. 方法都会遍历一遍数组, 对每个元素执行一次回调函数
2. 如果value的值是引用数据类型(对象/数组) 可以影响正在遍历的数组 (基础数据类型没有影响)
//===========示例================
// 1. forEach() 单纯遍历
var arr = ["弟弟", "妹妹", "哥哥", "小姐姐"];
arr.forEach(function(value, index, array){
console.log(value, index, array); // value是每一项的值, index是下角标(序号), array是当前数组arr (注意, 此函数会被触发数组的个数 次)
})
// 2. map() 遍历+返回 返回处理后的值的数组
// 需求: 想让每个元素+5, 返回一个全新的数组
var brr = [5, 1, 7, 3];
let brrRes = brr.map(function(value, index){
value = value + 5;
return value;
}) // 每个return的结果, 会被map收集起来, 放入一个全新的数组中, 在遍历后, 返回这个全新的数组
console.log(brrRes);// [10, 6, 12, 8]
// 3. filter() 遍历+过滤+返回
let ageArr = [10, 29, 35, 30, 36, 8, 18];
let ageRes = ageArr.filter(function(value){
return value >= 18;
}) // 如果当前遍历时, 此函数return 了一个 true, 那么当前value就会被filter收集起来, 循环结束后, 返回一个全新的数组
console.log(ageRes); // [29, 35, 30, 36, 18]
// 4. (重点2) reduce() 遍历+累计运算+返回累计结果
let crr = [1, 5, 9, 3, 0, 2];
let result = crr.reduce(function(sum, value){
sum = sum + value; // 往sum变量上累加
return sum;
}, 0);
// 注意1: reduce的参数2, 是给回调函数里第一个参数sum赋予初始值 相当于sum = 0;
console.log(result);
// 执行顺序:
// 第一次触发function, sum = 0; value = 1; sum 最新值 1, return sum 到下一次function触发时的 第一个参数上
// 第二次触发function, sum = 1; value = 5; sum 最新值 6
// 第三次触发funciton, sum = 6; value = 9; ...
// 循环结束了, 把最后sum的值return出去, 赋予给result
// 每次执行回调函数, 都会把每个值传入进去
// 面试题:
// 数组的方法, 在遍历时, 是不会修改原数组的
// 但是, 如果这个值是一个对象/数组 (引用类型), 是可以去改变对象/数组里的值 深拷贝
let myArr = [123, {age: 18}];
myArr.map(function(val, ind){
if (ind === 1) val.age = 29; // 如果只有一行代码, 可以省略{}
// val = 999;
})
console.log(myArr);
Function
bind()
会返回一个全新的函数, 不会马上让函数执行
修改函数内this的指向
//=======示例============
function Person(){
this.address = "安徽";
}
// 以前的 call() / apply() 做法:
let obj = {};
call() / apply() 改变函数内this的指向 Person.call(obj);
Person();
//bind() 做法:
let obj = {};
let NewFun = Person.bind(obj); // 返回一个跟Person功能一样的函数
PersonFn();
注意: apply() / call() 会马上触发函数执行一次, 对传入的对象绑定属性
而bind() 并不会马上触发函数执行, 会返回一个功能一模一样的函数(并且内部this已经被改变了), 但是这个函数还没有执行(所以obj上还没有被添加属性), 需要自己手动调用一次
ES6
20200429
简介
ES6是ECMAScript6的简写, 是继2009年ES5后, 在2015年发布的ES6标准, 其实就是新加入了一些特性
* ES5 : 2009年发布
* ES6 : 2015年发布, 也称为ECMA2015
* ES7 : 2016年发布, 也称为ECMA2016
* ....
let *
作用: 与var功能相同, 用于声明一个变量
特点:
块级作用域内有效
不会污染全局变量, 不添加到window属性上
不存在变量提升 (也叫, 暂时性死区), 同一作用域下变量名不能重复
//===========示例===============
let btns = document.getElementsByTagName('button');
for(let i = 0;i<btns.length;i++){
btns[i].onclick = function () {
alert(i);
}
}
拆解过程, 可以看图, for循环特殊, 每次循环i都在一个
本文来自博客园,作者:JackieDYH,转载请注明原文链接:https://www.cnblogs.com/JackieDYH/p/17633997.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现