### 可视化编辑网页
```http
document.body.contentEditable="true"
document.designMode = "on"
cmd copy 1.txt /b + 2.txt 3.txt
chrome://flags/
搜索 SameSite
SameSite by default cookies和Schemeful Same-Site设置为disabled
div.class$*3
div>p+span
span{$}*1000
rem 自动转px插件(px2rem)
ALT+D单个替换
CTRL+ALT全局替换
快捷方式->目标添加空格
--disable-features=SameSiteByDefaultCookies
1.打开cmd,查看当前镜像地址:
npm get registry
**2.**切换为淘宝镜像:
npm config set registry http://registry.npm.taobao.org/
3.切换为原本的npm镜像:
npm config set registry https://registry.npmjs.org/
npm install --global vue-cli
vue init webpack "项目名"
npm install
卸载2.x
npm uninstall -g vue-cli
下载3.x
npm install -g @vue/cli
vue create "项目名"
npm i
npm i vuex --save
npm i axios
npm i element-ui --save
npm i vue-resource --save (通过XMLHttpRequest或JSONP发起请求并处理响应)
npm i vue-router --save
npm i --save babel-runtime(es6编译成es5运行,前端可以使用es6的语法来写最终浏览器上运行的是es5)
npm i --save-dev babel-polyfill(Babel 默认只转换新的 JavaScript 语法,而不转换新的 API)
npm i fastclick -D
(作用:处理移动端 click 事件 300 毫秒延迟。
说明: 为什么存在延迟?从点击屏幕上的元素到触发元素的 click 事件,移动浏览器会有大约 300 毫秒的等待时间。为什么这么设计呢? 因为它想看看你是不是要进行双击(double tap)操作。)
安装:npm i --save lodash(Lodash是一个具有一致接口、模块化、高性能等特性的 JavaScript 工具库)
原生js:
<script src="http://wechatfe.github.io/vconsole/lib/vconsole.min.js?v=3.2.0"></script>
<script>
// init vConsole
var vConsole = new VConsole();
console.log('Hello world');
</script>
npm 安装
npm install vconsole
@change当输入框失焦的时候触发
而且在elementUI中使用change时是这样的@visible-change
@input是输入框发生变化时触发,也就是说输入框一动就出触发了
子组件
{{ msghello }}
{{ user.lastName }}
父组件
{{headertest.user}}
{{headertest.user2}}
{{ slotProps.user.firstName }}
ref
property 或 reactive
对象给 provide
来改变这种行为// 父组件中
// 子组件中
-
{{ item.label }}
// 父组件中
// 子组件
// main.js
Vue.prototype.$bus = new Vue() // event Bus 用于无关系组件间的通信。
// a组件 接受
mounted() {
this.$bus.$on('isCalled', this.isCalled)
this.$bus.$on('missCall', this.missCall)
}
// b组件 发送
handleEvent(messageList) {
if (xxxx) {
this.$bus.$emit('isCalled')
}
if (xxx) {
this.$bus.$emit('missCall')
}
}
//相当于又new了一个vue实例,Event中含有vue的全部方法;
var Event = new Vue();
//发送数据,第一个参数是发送数据的名称,接收时还用这个名字接收,第二个参数是这个数据现在的位置;
Event.$emit('msg',this.msg);
//接收数据,第一个参数是数据的名字,与发送时的名字对应,第二个参数是一个方法,要对数据的操作
Event.$on('msg',function(msg){
/这里是对数据的操作
})
在入口js文件main.js中引入,一些公共的样式文件,可以在这里引入
import Vue from 'vue'
import App from './App' // 引入App这个组件
import router from './router' /* 引入路由配置 */
import axios from 'axios'
import '../static/css/global.css' /*引入公共样式*/
在index.html中引入
<link rel="stylesheet" href="./static/css/global.css"> /*引入公共样式*/
在app.vue中引入,但是这样引入有一个问题,就是在index.html的HEADH上会多出一个空的
对象,键,值
直接给student赋值操作,虽然可以新增属性,但是不会触发视图( 页面 )更新
原因是:vue.js的属性必须在 data 对象上才能让 Vue.js 转换它,才能让它是响应的。这里就可以使用this.$set了
子组件
监听方法的参数就是父组件传过来的值,监听变化因为数据变了所以调一下查看接口也就是刷新数据
watch: {
childId(newVal) {
this.childId = newVal;
this.getList(); //一定要刷新数据否则页面不刷新
console.log(newVal, "这里是监听"); //这个参数就是传来的所有值
}
},
在子组件props接收是number类型
props: {
childId: Number
}
传给后端
id:this.childId
deep: true //深度监听
$route.path 字符串,等于当前路由对象的路径,会被解析为绝对路径,如/home/ews
$route.params 对象,含路有种的动态片段和全匹配片段的键值对,不会拼接到路由的url后面
$route.query 对象,包含路由中查询参数的键值对。会拼接到路由url后面
$route.router 路由规则所属的路由器
$route.matchd 数组,包含当前匹配的路径中所包含的所有片段所对象的配置参数对象
$route.name 当前路由的名字,如果没有使用具体路径,则名字为空
cnpm install element-ui -S (pc端的)
cnpm install mint-ui -S (移动端的)
cnpm install vant -S (移动端的)
https://blog.csdn.net/dlnu2015250622/article/details/105204478/
import store from '@/assets/store' //把这个userId获取过来
router.beforeEach((to,from,next)=>{
if(to.meta.requireAuth){
if(store.state.userId){
next()
}else{
next({path:'/b'})
}
}else{
next()
}
})
方式1:nginx代理
不过要知道在生产中,要么使用 CORS 、要么使用 Nginx 反向代理来解决跨域。在 Nginx 的配置文件中进行如下配置即可:
server {
listen 80;
server_name localhost; # 用户访问 localhost,反向代理到 http://webcanteen.com
location / {
proxy_pass http://webcanteen.com
}
}
方式2:vue.config.js文件中
proxy: {
'/api': {
target: 'https://you.163.com/', //接口域名
changeOrigin: true, //是否跨域
ws: true, //是否代理 websockets
secure: true, //是否https接口
pathRewrite: { //路径重置
'^/api': ''
}
}
}
src下创建文件
config文件->http.js下
import axios from "axios";
//import store from "../store"
var instance = axios.create({
baseURL:'http://www.jiaju.com',
});
// 添加请求拦截器
instance.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
if (store.state.token) {
config.headers.token=store.state.token;
}
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
instance.interceptors.response.use(function (response) {
// 对响应数据做点什么
if (response.data.code==999){
window.location.href="/";
}else{
return response;
}
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
export default instance;
api文件->index.js下
import login from "./Login"
import carousel from "./carousel"
import category from "./category"
export default {
login,
carousel,
category,
}
其他接口页面->例如:good.js
import http from '../config/http.js';
export default {
post(data){
return http.post('/goods',data)
},
get(page,){
return http.get(`/goods?page=${page}`)
},
}
main.js文件下
Vue.prototype.$http=Axios;
import api from "../../api/index"
api.recom.get().then(res=>{
this.tableData = res.data.data;
}).catch(err=>{
this.$message({
type:'error',
message:'获取失败'
})
})
api.recom.post(this.formLabelAlign).then(res=>{
if (res.data.code == 200){
this.$message({
type:'success',
message:'添加成功'
});
this.dialogFormVisible = false;
this.gettpl();
this.formLabelAlign = {}
} else{
this.$message({
type:"error",
message:'添加失败'
})
}
}).catch(error=>{
this.$message({
type:"error",
message:'添加失败'
})
})
:show-overflow-tooltip="true"
var a = "天津市11111公司"
var c = a.replace(/(?<=市)(\S*)(?=公)/, "****")
console.log(c);
{ pattern: /^1(3\d|47|5((?!4)\d)|7(0|1|[6-8])|8\d)\d{8,8}$/, // required: true, message: '请输入正确的手机号', // trigger: 'blur'},
{ pattern: /^[0-9]*$/,message: '只能输入数字'},
shijiantime(times) {
var timearr = times.replace(" ", ":").replace(/\:/g, "-").split("-");
var timestr = "" + timearr[0] + "-" + timearr[1] + "-" + timearr[2]
// var timestr = "" + timearr[1].split("")[1] + "月" + timearr[2] + "日\t" + timearr[3] + ":" + timearr[4] + ""
return timestr
},
str = "12345?789”
str.split("?")[0] 输出为 12345
str.split("?")[1] 输出为 789
//组件上增加
:key="math"
data:{
math:0
}
math +=1
npm init vite-app app
cd app
npm install
npm run dev
npm install vue@next
vue upgrade --next //升级cli版本
immediate
为true
, 来指定初始时立即执行第一次
//如果使用 name
// 新
npm install [email protected]
"dev": "vite --port 8085",
Vite 是一个 web 开发构建工具,由于其原生 ES 模块导入方式,可以实现闪电般的冷服务器启动。
通过在终端中运行以下命令,可以使用 Vite 快速构建 Vue 项目。
使用 npm:
$ npm init vite <project-name> -- --template vue
$ cd <project-name>
$ npm install
$ npm run dev
或者 yarn:
$ yarn create vite <project-name> --template vue
$ cd <project-name>
$ yarn
$ yarn dev
webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部构建一个 依赖图(dependency graph),此依赖图对应映射到项目所需的每个模块,并生成一个或多个 bundle
入口(entry)
输出(output)
loader
插件(plugin)
模式(mode)
浏览器兼容性(browser compatibility)
环境(environment)
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装
const webpack = require('webpack'); // 用于访问内置插件
module.exports = {
//入口
entry: './path/to/my/entry/file.js',
// 输出
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js',
},
// 模式
mode: 'production',
// loader
module: {
rules: [{ test: /\.txt$/, use: 'raw-loader' }],
},
// 插件
plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
};
type=“number”
Document
42341
缩放
transform: scale(1.05, 1.05);
-ms-transform: scale(1.05, 1.05);
/* IE 9 */
-webkit-transform: scale(1.05, 1.05);
/* Safari and Chrome */
transition: 0.3s;
const regex = new RegExp('
String字符串截取操作
substr(start,length) 返回从start位置开始length长度的子串
substring(start,end) 返回从start位置开始到end位置的子串(不包含end)
//1 取字符串的前i个字符
str=str.substring(0,i);
//2 去掉字符串的前i个字符
str=str.substring(i);
//3 从右边开始取i个字符
str=str.substring(str.length()-i);
str=str.substring(str.length()-i,str.length());
//4 从右边开始去掉i个字符
str=str.substring(0,str.Length-i);
//5 如果字符串中有"abc"则替换成"ABC"
str=str.replace("abc","ABC");
Array数组截取操作
var heros=["李白",'蔡文姬','韩信','赵云','甄姬','阿珂','貂蝉','妲己'];
console.log(heros.slice(1,4))// [ "蔡文姬", "韩信", "赵云" ]开始索引为1 结束索引为4(不包括4)
console.log(heros)// 不改变原数组 [ "李白", "蔡文姬", "韩信", "赵云", "甄姬", "阿珂", "貂蝉", "妲己" ]
//若开始索引为负数,则将该值加上数组长度后作为开始索引,如果此时还是负数,开始索引为0。
var heros=["李白",'蔡文姬','韩信','赵云','甄姬','阿珂','貂蝉','妲己'];
console.log(heros.slice(-6,4))// [ "韩信", "赵云" ]开始索引为2 结束索引为4(不包括4)
console.log(heros.slice(-10,4))// [ "李白", "蔡文姬", "韩信", "赵云" ]开始索引为0 结束索引为4(不包括4)
//如果结束索引省略,截取到数组的末尾。如果为负,数组长度加上该值即为结束索引,如果此时还为负数,返回空数组
var heros=["李白",'蔡文姬','韩信','赵云','甄姬','阿珂','貂蝉','妲己'];
console.log(heros.slice(1))// [ "蔡文姬", "韩信", "赵云", "甄姬", "阿珂", "貂蝉", "妲己" ]
console.log(heros.slice(1,-4))// [ "蔡文姬", "韩信", "赵云" ] 开始索引1 结束索引8+(-4)=4
console.log(heros.slice(1,-10)) //[ ] 开始索引1 结束索引8+(-10)=-2
var heros=["李白",'蔡文姬','韩信','赵云','甄姬','阿珂','貂蝉','妲己'];
//当只有索引,从当前索引截取到最后
console.log(heros.splice(1))// [ "蔡文姬", "韩信", "赵云", "甄姬", "阿珂", "貂蝉", "妲己" ]
console.log(heros) //['李白']
//当第二个参数(删除数量)小于0视为0
var heros=["李白",'蔡文姬','韩信','赵云','甄姬','阿珂','貂蝉','妲己'];
console.log(heros.splice(1,-10))//[]
console.log(heros) // [ "李白", "蔡文姬", "韩信", "赵云", "甄姬", "阿珂", "貂蝉", "妲己" ]
//删除并添加
var heros=["李白",'蔡文姬','韩信','赵云','甄姬','阿珂','貂蝉','妲己'];
console.log(heros.splice(1,2,['扁鹊'],'孙膑'))//[ "蔡文姬", "韩信" ]
console.log(heros) //[ "李白", [扁鹊], "孙膑", "赵云", "甄姬", "阿珂", "貂蝉", "妲己" ]
oninput =“value=value.replace(/[^\d]/g,'')” //只能输入数字
oninput =“value=value.replace(/[^0-9.]/g,’’)” //只能输入数字和小数
客户端脚本语言。
h5(css3 JS ):
1.语义化
2.表单标签
3.本地存储
4.表单属性
5.canvas 画布
6.audio video音频 视频
git svn:分布式版本控制系统;
完成页面交互效果;
数据验证
动态创建元素
动态操作元素的属性样式
ajax 100%
变量(命名规范、赋值)、数据类型(基本、引用)、运算符(算术运算符、关系、赋值、逻辑)、流程
控制(顺序、条件、循环)、数组(方法)、函数(定义、调用、参数、返回值、默认值)、对象(定义、原型、原型链、继承、this、this改变方式)、作用域(全局、局部、块级、作用域链、闭包)、字符串、日期、Math
window对象、location对象、history对象、document对象
获取元素、操作元素的内容、属性、样式、节点、元素的尺寸与位置、事件(添加事件的方式、事件的分类、事件流、事件委派)
基于
对象
与事件驱动
与松散型
、解释型
语言。
单线型
、异步机制
<script src="demo.js"></script>
在script标签对中写js代码
1.嵌入式的script标签上边不写src属性
2.外部引入方式中的js文件不写script标签对
3.几种js引入方式都是相互关联的,可以进行相互操作
console.log(1)
alert("a")
document.write("b")
document.write("识别标签对
");
prompt("请输入一个数")
confirm("确定退出吗"); //true false
单行注释:// ctrl+/
块级注释:/**/ ctrl+shift+/
一个容器,用来存储数据;
利用var关键字声明变量。
数字、字母、下划线、$
1.先声明后赋值:`var a;a=12;
2.声明的同时赋值
3.一次性声明多个变量在赋值,用逗号隔开
4.一次性声明多个变量同时赋值
先声明后使用
变量的默认值为undefind
新值覆盖旧值
变量可以重复声明
不用var
关键字声明变量,但是赋值了,不报错,这个变量是全局变量
不用var
关键字声明变量,但是没有赋值,会报错
先使用后声明,会输出默认值,`undefined.预解析(var,function)与解析;
变量中存放的数据的类型,按照数据在内存中的存储位置,分为基本数据类型与引用数据类型;
number(数字型):正数、负数、小数、二进制、八进制、十进制、十六进制、科学计数
NaN:特殊的number型(not a number).期望出现数字,但不会出现时,生成nan
string(字符串型):加单双引号
boolean(布尔型):true,false(真假)
undefined:变量声明但未赋值;变量直接赋值为undefined
null:直接赋值null,typeof的结果为object;
object:对象
数组、对象的数据类型是object
函数的数据类型是function
typeof null的结果是object
+
-
*
/
%
++var
var++
--var
var--
-
*
/
%
两个操作数是数字型,如果不是会隐式调用Number()函数,试图转换为数字型。true 1;false 0;
null 0;undefind NaN;数字型字符串转化为number,非数字型字符串转换为NaN;
+
`${i}-${j}`
var++
++var
++在前,先做本条语句中的加法运算,再做其他运算;
++在后先做其他语句中的其他运算,在做加法运算;
< > >= == === != !==
返回值为布尔值;
true
==1 false
==0==
要求数值相等 ===
要求数据类型、数值相等;undefind==null
= += -= *= /= %=
var num=10;
num+=12;
console.log(num); 输出22
false、null、undefind、0、NaN、空字符串 -> false;
同真为真.返回第一个假值,如果没有假值,返回最后一个真值
同假为假,返回第一个真值,如果没有真值,返回最后一个假值;
取反
//当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数
const nullValue = null;
const emptyText = ""; // 空字符串,是一个假值,Boolean("") === false
const someNumber = 42;
const valA = nullValue ?? "valA 的默认值";
const valB = emptyText ?? "valB 的默认值";
const valC = someNumber ?? 0;
let a;
let b = a ?? 5;
console.log(b); // 5
console.log(valA); // "valA 的默认值"
console.log(valB); // ""(空字符串虽然是假值,但不是 null 或者 undefined)
console.log(valC); // 42
//允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为空(nullish ) (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值
let customer = {
details: {
age: {
num: '999',
getsonme:function(){
return "有"
}
},
}
};
let customerCity = customer.details?.age?.nu ?? "无"
//age是否存在?存在则继续链式.nu<值为undefind,所以返回 无>
console.log(customerCity); //无
let yes = customer.details?.age?.getsonme() ?? "无"
console.log(yes) //有
let x = null;
let y = 2;
x &&= y;
console.log(x); // 2
//如果x存在,则赋值,否则返回x
//等价于
x && (x = y)
//或者等价于
if(x) {
x = y
}
let x = 1;
let y = 2;
x ||= y;
console.log(x); // 1
let x;
let y = 2;
x ??= y;
console.log(x); // 2
A | B | A&&B | A||B | !A |
---|---|---|---|---|
T | T | T | T | F |
F | F | F | T | F |
T | F | F | T | T |
F | T | F | T | T |
条件?值1:值2;
判断条件的真假,如果条件为真,执行1;如果为假,执行2;
,
一次性声明多个变量()
提高优先级;代码的执行顺序
满足一定条件时;执行相应的代码;
if(条件){
满足条件执行的代码;
}
if(条件){
满足条件时执行的代码;
}else{
不满足条件时执行的代码;
}
if(条件){
满足条件1时执行的代码;
}else if{
不满足条件1,满足条件2时执行的代码;
}else if{
不满足条件1和2,满足条件3时执行的代码;
}
else{
以上条件都不满足时执行的代码
}
if(){
if(){}else{}
}else{
if(){}else{}
}
switch(变量){
//值为变量能够取到的结果;值与变量的数据类型相同;
case"值1":语句1;break;(终止)
case"值2":语句2;break;
case"值3";语句3;break;
default:以上条件都不满足时执行此语句;
}
满足一定条件时,重复执行一段代码;
for(初始条件;终止条件;步行值){
循环体;
}
while(条件){
循环体
}
do{
循环体
}while(条件)
存储一系列相关信息;
// 使用数组字面量表示法
var arr=[];
// 使用array构造函数
var arr1 = new Array(); //创建一个空数组
var arr1 = new Array(20); //创建一个长度为20的空数组
// Array.of 方法创建数组(es6 新增)
let arr = Array.of(1, 2);
console.log(arr.length);//2
let arr1 = Array.of(3);
console.log(arr1.length);//1
console.log(arr1[0]);//3
let arr2 = Array.of( 2 );
console.log(arr2.length);//1
console.log(arr2[0]);// 2
// Array.from 方法创建数组(es6 新增)
function arga(...args) { //...args剩余参数数组,由传递给函数的实际参数提供
let arg = Array.from(args);
console.log(arg);
}
arga( arr1 , 26, from ); // [ arr1 ,26, from ]
var arr=[1,2,3,4]
var =[]
arr[0]=1,arr[1]=3; //通过下标赋值
通过下标去访问;
arr[下标]
,下标开始为0,结束为arr.length-1
arr.length
全部访问每一个元素;
for(var i=0;i<arr.length;i++){
arr[i];
}
数组的每一个元素数据类型还是数组;
arr[i][j] arr[0][0]
var arr=[[1,2,3],[2,3,],[true]];
for(var i=0;i<arr.length;i++){
for(var j=0;j<arr[i].length;j++){
arr[i][j];
}
}
var arr1=arr;
var arr1=[];
for(var i=0;i<length;i++){
arr1.push(arr[i]);
}
function functionname(){
}
var variable=function(){
函数体
}
实例化构造函数
functionName()
variable()
使函数更加灵活;
定义函数里括号中的叫形参(目的是接受实参)
调用函数里括号里的叫实参,目的是给形参传值。
arguments:
for(var i=0;i
剩余参数:
function fn(a,b,...rest){
console.log(rest);
for(var i=0;i<rest.length;i++){
rest[i];
}
}
进行数据类型转换;ECMAscript自带的函数,在全局都能访问的函数;
0 null NaN undefind 空字符串 false
识别数字开头(+、-、空格)的到数字结尾的字符串;其余返回NaN;
识别数字开头(+、-、空格)的到数字结尾的字符串,其余返回NaN;
隐式数据类型转换;
强制数据类型转换;
把一个函数传递给另一个函数,当做参数的这个函数调用时就叫做回调函数;
变量起作用的范围;
在函数外部用var关键字声明的变量;
不用var关键字声明但赋值的变量;
{ } let const
let:
let 用来声明变量,可以识别块级作用域;
let不存在变量提升 (先访问后声明) ;
let不可以重复声明;
const
- const用来声明常量。声明的同时赋值;可以识别块级作用域;
- const不存在变量提升;
- const不可以重复声明;
作用域链:
为变量赋值时遵循的一条规则,从内到外进行访问,局部作用域优先于全局作用域;
在函数内部用var关键字声明的变量
形参是局部变量;
(function(){}());
call() 方法分别接受参数。
apply() 方法接受数组形式的参数
// apply
let ob1 = {
namefunc: function (city, rural) {
return `${this.firstname},${city},${rural}`
}
}
let ob2 = {
firstname: '郭辛强'
}
let ob3 = ob1.namefunc.apply(ob2, ["万安镇", "兰家节村"])
console.log(ob3); /*郭辛强,万安镇,兰家节村*/
function Computer(color,size,price){
this.color=color;
this.size=size;
this.price=price;
this.code=function(){
"敲代码"
}
this.play=function(){
"玩游戏"
}
}
let apple=new computer("white",100,100000);
let asus=new computer("black",10,1000000);
console.log(apple);//访问对象;
console.log(asus);//访问对象;
apple.band="APPLE";//添加属性;
console.log(apple.color);//访问属性;0 b
console.log(apple.play);//访问方法;
delete apple.color;//删除属性;
apple.color="red";//修改属性(直接覆盖);
for(let i in apple){//访问;
console.log(i);//键 属性名;
console.log(apple[i]);//值 属性 方法;
}
console.log(apple.constructor);//显示构造函数
let apple={
color:"white",
size:15.6,
price:10000,
code:function(){
console.log(code)
},
play:function(){
console.log(play)
}
}
console.log(apple.color);
apple.code();
for(let i in apple){
console.log(apple[i])
},
for(let i in apple){
console.log(i);
}
console.log(apple.constructor);//显示构造函数
class computer{
constructor(color){
this.color=color;
this.size=size;
}
play(num){
console.log(num);
console.log(this.color);
}
}
let apple=new Computer("red");
var obj=new object();
for(let i in obj){
i;// 键 属性名
object[i];//值 属性 方法
}
对象的属性,返回对象的构造函数; apple.constructor
console.log(对象 instanceof 构造函数),用来判断对象的构造函数,是true,否false;
Person.prototype={
height:180,
code:function(){
}
}
--proto--
对象拥有的属性;
对象的–proto–属性。指向构造函数的原型对象;
--proto--
形成原型链,实现继承;
继承顺序:找自己、找构造函数、找原型对象、Object.prototype、null;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HIXt818i-1639533983784)(C:\Users\Administrator.USER-20190109DE\Desktop\JS\原型链继承.png)]
寻找对象属性与方法时遵循的规则;实现继承。
function Markey() {
this.color="brown";
this.height=180;
}
Markey.prototype.play=function(){
console.log("game");
};
function Parson() {
this.character="Extroversion";
this.gander="man";
}
Parson.prototype=new Markey();
Parson.prototype.play=function () {
console.log("wan");
}
Parson.prototype.height=110;
let student=new Parson();
console.log(student);
console.log(student.__proto__==Parson.prototype);
console.log(Parson.prototype.__proto__==Markey.prototype);
console.log(Markey.prototype.__proto__==Object.prototype);
console.log(Object.prototype.__proto__ == null);
__proto__
:指向构造函数的原型对象;arr.concat([1,2,3,4])
链接一个或多个数组,不会改变原数组;arr.every(function(ele,index,obj){return ele>0
}).当所有元素都满足条件是,返回true,否则返回false;arr.fill("a",start,end)
用于将一个固定值替换数组的元素,会影响原数组;arr.filter(function(ele,index){return ele>2})
过滤,从一个集合到另一个更小的集合;arr.map(function(ele){return ele*2})
arr.find(function(ele){return ele>2})
返回满足条件的第一个元素,没有满足返回false;arr.findindex(function(ele){return ele>2})
返回满足条件的第一个元素的下标,否则返回-1;arr.forEach(function(ele,index){console.log(ele)})
遍历数组;arr.includes(1)
判断是否包含指定元素,包含返回true,否则返回false;arr.lastIndexOf(1)
返回包含指定元素的下标(从后往前找),不包含返回-1;arr.join("-")
将数组转换为字符串,默认用逗号拼接;arr.toString()
将数组转换为字符串,只能用逗号拼接;arr.push("a")
向数组的后面添加一个元素或多个元素,返回新数组的长度,影响原数组;arr.pop()
删除数组的最后一个元素,返回删除的元素,会影响原素组;arr.reduce(function(tot,ele){return tot+ele})
从·从前向后累加;arr.reduceRight(function(tot,ele){return tot+ele})
从后向前累加;arr.reverse()
反转,影响原数组;arr.unshit("a","b")
在数组的前面插入一个或多个元素,返回新数组的长度,影响原数组;arr.shift()
删除数组的第一个元素,返回被删除的元素,影响原数组;arr.sort(function(a,b){return a-b})
排序a-b从小到大,b-a从大到小;arr.slice(start,end)
截取 从start位置开始到end位置,但不包含end在内;arr.splice(index,num);
arr.splice(index,0,item1,item2);
arr.splice(index.4,item1,item2);
Math | 属性 | 方法 | |
---|---|---|---|
PI | 属性就是 π,即圆的周长和它的直径之比。 | Math.PI | document.write("PI: " + Math.PI); |
abs(x) | 返回数的绝对值。 | x 必需。必须是一个数值。 | document.write(Math.abs(7.25) + “ ”) |
ceil(x) | 可对一个数进行向上取舍 | ceil() 方法执行的是向上取整计算,它返回的是大于或等于函数参数,并且与之最接近的整数。 | document.write(Math.ceil(0.60) + “ ”) |
floor(x) | 可对一个数进行下舍入 | floor() 方法执行的是向下取整计算,它返回的是小于或等于函数参数,并且与之最接近的整数。 | document.write(Math.floor(0.60) + “ ”) |
log(x) | 可返回一个数的自然对数 | 参数 x 必须大于 0。 | document.write(Math.floor(0.60) + “ ”) |
max(x,y) | 返回 x 和 y 中的最高值。 | 参数中最大的值。如果没有参数,则返回 -Infinity。如果有某个参数为 NaN,或是不能转换成数字的非数字值,则返回 NaN。 | x: 0 或多个值。在 ECMASCript v3 之前,该方法只有两个参数。 |
min(x,y) | 返回 x 和 y 中的最低值。 | 参数中最小的值。如果没有参数,则返回 Infinity。如果有某个参数为 NaN,或是不能转换成数字的非数字值,则返回 NaN。 | document.write(Math.min(5,7) + “ ”) |
pow(x,y) | 返回 x 的 y 次幂。 | 如果结果是虚数或负数,则该方法将返回 NaN。如果由于指数过大而引起浮点溢出,则该方法将返回 Infinity。 | |
random() | 返回 0 ~ 1 之间的随机数。 | 0 到1之间的一个伪随机数。(不包括1) | |
round(x) | 把数四舍五入为最接近的整数。 | 与 x 最接近的整数。 | |
sqrt(x) | 返回数的平方根。 | 参数 x 的平方根。如果 x 小于 0,则返回 NaN。 | |
toSource() | 返回该对象的源代码。 | 该方法在 Internet Explorer 中无效。 | |
valueOf() | 返回 Math 对象的原始值。 | 该原始值由 Math 对象派生的所有对象继承。 valueOf() 方法通常由 JavaScript 在后台自动调用,并不显式地出现在代码中。 |
源代码:toSource的用法:
function employee(name,job,born)
{
this.name=name;
this.job=job;
this.born=born;
}
var bill=new employee("Bill Gates","Engineer",1985);
document.write(bill.toSource());
替换:
重复:
转换:
var str = "123";console.log(str.indexOf("3") != -1 ); // true
indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。如果要检索的字符串值没有出现,则该方法返回 -1。
lastIndexOf() 方法返回指定文本在字符串中最后一次出现的索引:
var str = "The full name of China is the People's Republic of China.";console.log(str.lastIndexOf("China"));//51,如果未找到,同indexOf一样返回-1
length 属性返回字符串的长度:
var txt = "webqdkf.com-web前端开发";var sln = txt.length;//15
var str = "123";console.log(str.search("3") != -1 ); // true
search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。如果没有找到任何匹配的子串,则返回 -1。
你注意了吗?indexOf() 与 search()是相等的。这两种方法是不相等的。区别在于:
search() 方法无法设置第二个开始位置参数。
indexOf() 方法无法设置更强大的搜索值(正则表达式)。
slice() 提取字符串的某个部分并在新字符串中返回被提取的部分。该方法设置两个参数:起始索引(开始位置),终止索引(结束位置)。
这个例子裁剪字符串中位置 7 到位置 13 的片段:
var str = "Apple, Banana, Mango";var res = str.slice(7,13);//Banana
如果某个参数为负,则从字符串的结尾开始计数。这个例子裁剪字符串中位置 -12 到位置 -6 的片段:
var str = "Apple, Banana, Mango";var res = str.slice(-13,-7);
如果省略第二个参数,则该方法将裁剪字符串的剩余部分:
var res = str.slice(7);
或者从结尾计数:
var res = str.slice(-13);
substring() 类似于 slice()。不同之处在于 substring() 无法接受负的索引。
var str = "Apple, Banana, Mango";var res = str.substring(7,13);//res 的结果是:Banana
如果省略第二个参数,则该 substring() 将裁剪字符串的剩余部分。
substr() 类似于 slice()。不同之处在于第二个参数规定被提取部分的长度。
var str = "Apple, Banana, Mango";var res = str.substr(7,6);//res 的结果是:Banana
如果省略第二个参数,则该 substr() 将裁剪字符串的剩余部分。
var str = "Apple, Banana, Mango";var res = str.substr(7);//res 的结果是:Banana, Mango
如果首个参数为负,则从字符串的结尾计算位置。
var str = "Apple, Banana, Mango";var res = str.substr(-5);//res 的结果是:Mango
第二个参数不能为负,因为它定义的是长度。
replace() 方法用另一个值替换在字符串中指定的值:
str = "Please visit Microsoft!";var n = str.replace("Microsoft", "fly63");
replace() 方法不会改变调用它的字符串。它返回的是新字符串。默认地,replace() 只替换首个匹配:
str = "Please visit Microsoft and Microsoft!";var n = str.replace("Microsoft", "fly63");//'Please visit Microsoft and Microsoft!'
默认地,replace() 对大小写敏感,因此不对匹配 MICROSOFT。如需执行大小写不敏感的替换,请使用正则表达式 /i(大小写不敏感):
str = "Please visit Microsoft!";var n = str.replace(/MICROSOFT/i, "fly63");
请注意正则表达式不带引号。如需替换所有匹配,请使用正则表达式的 g 标志(用于全局搜索)
通过 toUpperCase() 把字符串转换为大写:
var text1 = "Hello World!"; // 字符串var text2 = text1.toUpperCase(); // text2 是被转换为大写的 text1
通过 toLowerCase() 把字符串转换为小写:
var text1 = "Hello World!"; // 字符串var text2 = text1.toLowerCase(); // text2 是被转换为小写的 text1
concat() 连接两个或多个字符串:
var text1 = "Hello";var text2 = "World";text3 = text1.concat(" ",text2);//Hello World
concat() 方法可用于代替加运算符。下面两行是等效的:
var text = "Hello" + " " + "World!";var text = "Hello".concat(" ","World!");
所有字符串方法都会返回新字符串。它们不会修改原始字符串。正式地说:字符串是不可变的:字符串不能更改,只能替换。
trim() 方法删除字符串两端的空白符:
var str = " Hello World! ";alert(str.trim());
警告:Internet Explorer 8 或更低版本不支持 trim() 方法。如需支持 IE 8,您可搭配正则表达式使用 replace() 方法代替:
var str = " Hello World! ";alert(str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''));
您还可以使用上面的 replace 方案把 trim 函数添加到 JavaScript String.prototype:
if (!String.prototype.trim) { String.prototype.trim = function () { return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');};var str = " Hello World! ";alert(str.trim());
charAt() 方法返回字符串中指定下标(位置)的字符串:
var str = "HELLO WORLD";str.charAt(0); // 返回 H
charCodeAt() 方法返回字符串中指定索引的字符 unicode 编码:
var str = "HELLO WORLD";str.charCodeAt(0); // 返回 72
可以通过 split() 将字符串转换为数组:
var txt = "a,b,c,d,e"; // 字符串txt.split(","); // 用逗号分隔txt.split(" "); // 用空格分隔txt.split("|"); // 用竖线分隔
如果省略分隔符,被返回的数组将包含 index [0] 中的整个字符串。
如果分隔符是 “”,被返回的数组将是间隔单个字符的数组:
var txt = "Hello"; // 字符串txt.split(""); // 分隔为字符
ECMAScript 5 (2009) 允许对字符串的属性访问 [ ]:
var str = "HELLO WORLD";str[0]; // 返回 H
使用属性访问有点不太靠谱:
var str = "HELLO WORLD";str[0] = "A"; // 不产生错误,但不会工作str[0]; // 返回 H
提示:如果您希望按照数组的方式处理字符串,可以先把它转换为数组。
var str = "123";var reg = RegExp(/3/);if(str.match(reg)){ // 包含 }
match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。
var str = "123";var reg = RegExp(/3/);console.log(reg.test(str)); // true
test() 方法用于检索字符串中指定的值。返回 true 或 false。
var str = "123";var reg = RegExp(/3/);if(reg.exec(str)){ // 包含 }
exec() 方法用于检索字符串中的正则表达式的匹配。返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为 null。
负责窗口与窗口之间的通信;window对象是其核心对象;
history
location
dom
screen(屏幕)
navigation(航行)
frames(框架)
closed | 返回窗口是否已被关闭。 |
---|---|
defaultStatus | 设置或返回窗口状态栏中的默认文本。 |
document | 对 Document 对象的只读引用。(请参阅对象) |
frames | 返回窗口中所有命名的框架。该集合是 Window 对象的数组,每个 Window 对象在窗口中含有一个框架。 |
history | 对 History 对象的只读引用。请参数 History 对象。 |
innerHeight | 返回窗口的文档显示区的高度。 |
innerWidth | 返回窗口的文档显示区的宽度。 |
localStorage | 在浏览器中存储 key/value 对。没有过期时间。 |
length | 设置或返回窗口中的框架数量。 |
location | 用于窗口或框架的 Location 对象。请参阅 Location 对象。 |
name | 设置或返回窗口的名称。 |
navigator | 对 Navigator 对象的只读引用。请参数 Navigator 对象。 |
opener | 返回对创建此窗口的窗口的引用。 |
outerHeight | 返回窗口的外部高度,包含工具条与滚动条。 |
outerWidth | 返回窗口的外部宽度,包含工具条与滚动条。 |
pageXOffset | 设置或返回当前页面相对于窗口显示区左上角的 X 位置。 |
pageYOffset | 设置或返回当前页面相对于窗口显示区左上角的 Y 位置。 |
parent | 返回父窗口。 |
screen | 对 Screen 对象的只读引用。请参数 Screen 对象。 |
screenLeft | 返回相对于屏幕窗口的x坐标 |
screenTop | 返回相对于屏幕窗口的y坐标 |
screenX | 返回相对于屏幕窗口的x坐标 |
sessionStorage | 在浏览器中存储 key/value 对。 在关闭窗口或标签页之后将会删除这些数据。 |
screenY | 返回相对于屏幕窗口的y坐标 |
self | 返回对当前窗口的引用。等价于 Window 属性。 |
status | 设置窗口状态栏的文本。 |
top | 返回最顶层的父窗口。 |
窗口的大小:
window.innerWidth(浏览器的宽度) ie8及以下的浏览器不支持;
window.innerHeight(浏览器的高度)
document.documentElement.clientWidth 浏览器的高度 ie8及以下的浏览器支持
document.documentElement.clientHeight 浏览器的高度
window.screenLeft 浏览器距离窗口左边的距离
window.screenTop 浏览器距离窗口顶部的距离
history.forword() 前进
history.back() 后退
history.go() 刷新
document.getElementById("box"); //id名
document.getElementsByClassName("类名");
document.getElementByTagName("标签名");
document.querySelector("选择器");
document.querySelectorAll("选择器");
行内 obj.style.color="#fff"
obj.classList.add("box")
添加类obj.classList.remove("box")
移出类obj.classList.toggle("box")
切换类操作id
obj.id="box"
添加id
obj.id=""
删除id
obj.style.background
getComputedStyle(obj,null).width
obj.src
obj.src=属性值
obj.setAttribute(属性名,属性值)
obj.getAttribute(属性名)
window.onscroll=function(){
let top=document.body.scrollTop=document.documentElement.scrollTOP;
let top=document.body.scrollLeft=document.documentElement.scrollLeft;
}
nodeType节点类型 | nodeName节点名称 | nodeValue节点值 | |
---|---|---|---|
文档节点 | 9 | #document | null |
元素节点 | 1 | 大写的标签名 | null |
属性节点 | 2 | 属性名 | 属性值 |
注释节点 | 8 | #comment | 注释的内容 |
文本几点 | 3 | #text | 文本内容 |
创建:document.createElement(标签名);
插入:父节点 . appendChild(新节点); 插入父节点的末尾
父节点 . insertBefore(新节点,被插入的节点)
删除:父节点 . removeChild(要删除的节点);
替换:父节点 . replaceChild(新节点,旧节点);
克隆:节点 . cloneNode() false:只克隆本节点,默认值; true:包括子节点内的内容;
鼠标:click,dblclick,mouseleave,mouseover,mouseout,mousemove,mouseenter;
键盘:keydown,keyup,keypress
window:load,scroll,resize
表单:focus,blur,submit,reset,input(表单输入事件),change(改变内容并失去焦点),
同一个事件源的同一个事件,可以添加多个事件处理函数;
obj.addEventLisenter(type,fn,false);
obj.addEventLisenter(type,function(){},false);
obj.removeEventListener("click",fn1);
记录事件发生时的详细信息;
key:键盘码;
keycode:键盘码对应的ASCll码;
alt 18 ctrl 17 shift 16
上(38)右(39)下(40)左(37)
offsetX,offsetY:获取距事件源左上角的水平、垂直方向距离;
clientX,clientY:获取距浏览器左上角的水平、垂直方向距离;
<a href="#">a>
<a href="javascript:;">a>
<a href="javascript:void(0);">a>
事件发生时会在元素节点与跟节点指尖按照特定顺序传播,路径经过的所有节点都会收到该事件,这个传播过程叫做DOM事件流
把原来加给子元素的事件绑定到父元素身上;
e.target:获得当前元素
存:localStorage.setltem(key,value);
取:localStorage.getltem(key)
删:localStorage.removeItem(key)
JSON.stringify():将对象转换为字符串;
JSON.parse():将字符串转换为对象;
localStorage\sessionStorage\cookis的区别:
cookis是网站为了标识用户身份而存储在用户本地终端(Client Side)上的数据(通常经过加密);
cookie数据始终在同源的http请求中携带(即使不需要),即会在浏览器和服务器间来回传递;
localStorage\sessionStorage不会自动把数据发给服务器,仅在本地保存;
存储大小:
cookie数据大小不能超过4k;
sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。 数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。 - 作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。Web Storage 支持事件通知机制,可以将数据更新的通知发送给监听者。Web Storage 的 api 接口使用更方便。
`localStorage、sessionStorage、cookie的区别:
//数字分隔符允许您在文字数字的数字之间添加下划线,这使它们更具可读性。当文件被解析时,这些下划线将被自动去除
let n1 = 1_000_000_000;
console.log(n1); // This will print: 1000000000
let n2 = 1_000_000_000.150_200
console.log(n2); // This will print: 1000000000.1502
// String 原型上的 replaceAll() 函数允许替换子字符串的所有实例,而无需使用正则表达式。如果在字符串上使用了 thereplace(),它只会替换该值的第一个实例。
// 另一方面,replaceAll() 提供替换该值的所有实例的功能
const orgStr = 'JavaScript, often abbreviated as JS, o the ECMAScript specification. JavaScript is h';
let newStr = orgStr.replace('JavaScript', 'TypeScript');
console.log(newStr);
// To replace all instances, use replaceAll().
let newStr2 = orgStr.replaceAll('JavaScript', 'TypeScript');
console.log(newStr2);
// Promise.any 与 Promise.all() 正好相反。如果任何承诺得到解决, Promise.any() 将被触发。
// 另一方面, Promise.all() 将等到所有承诺都得到解决。以下是 any()、all() 和 allSettled() 的区别。
// any() — 如果至少有一个承诺被解决,这将执行,如果所有承诺都被拒绝,则将拒绝。
// all() — 如果所有承诺都得到解决,这将执行,如果至少一个承诺被拒绝,则将拒绝。
// allSettled() — 如果所有承诺都已解决或被拒绝,这将执行
// Create a Promise.
const promise1 = new Promise((resolve, reject) => {
// After 2 seconds resolve the first promise.
setTimeout(() => resolve("The first promise has been resolved."), 2000);
});
// Create a Promise.
const promise2 = new Promise((resolve, reject) => {
// After 1 second resolve the second promise.
setTimeout(() => resolve("The second promise has been resolved."), 1000);
});
// Create a Promise.
const promise3 = new Promise((resolve, reject) => {
// After 3 seconds resolve the third promise.
setTimeout(() => resolve("The third promise has been resolved."), 3000);
});
(async function () {
const data = await Promise.any([promise1, promise2, promise3]);
// Print the data returned from the first resolved Promise.
console.log(data);
// The above will print: The second promise has been resolved.
})();
const promise1 = new Promise((resolve, reject) => {
// After 1 second reject the first promise.
setTimeout(() => reject("The first promise has been rejected."), 1000);
});
const promise2 = new Promise((resolve, reject) => {
// After 500 miliseconds reject the second promise.
setTimeout(() => reject("The second promise has been rejected."), 500);
});
(async function () {
try {
const data = await Promise.any([promise1, promise2]);
console.log(data);
} catch (error) {
// If all Promises gets rejected, then this try-catch block will handle
// the aggregate errors.
console.log("Error: ", error);
}
})();
// 逻辑 OR 赋值运算符 ||= 接受两个操作数,如果左操作数为假,则将右操作数分配给左操作数
// In the example, the ||= will check if the songsCount is false (0).
// If false, then the right value will be assigned to the left variable.
let myPlaylist = {songsCount: 0, songs:[]};
myPlaylist.songsCount ||= 100;
console.log(myPlaylist); // This will print: {songsCount: 100, songs: Array(0)}
a || (a = b)
// 如果左操作数为真,逻辑 AND 赋值运算符 &&= 仅将右操作数分配给左操作数
let myFiles = {filesCount: 100, files:[]};
myFiles.filesCount &&= 5;
console.log(myFiles); // This will print: {filesCount: 5, files: Array(0)}
a && (a = b)
// 如果左操作数为空或未定义,则空合并赋值运算符 ??= 仅将右操作数分配给左操作数。
let userDetails = {firstname: 'Katina', age: 24}
userDetails.lastname ??= 'Dawson';
console.log(userDetails); // This will print: {firstname: 'Katina', age: 24, lastname: 'Dawson'}
a ?? (a = b)
//默认情况下,类方法和属性是公共的,但可以使用哈希 # 前缀创建私有方法和属性。ECMAScript 2021 更新已强制执行隐私封装
class User {
constructor() {}
// The private methods can be created by prepending '#' before
// the method name.
#generateAPIKey() {
return "1111111111111";
}
getAPIKey() {
// The private methods can be accessed by using '#' before
// the method name.
return this.#generateAPIKey();
}
}
const user = new User();
const userAPIKey = user.getAPIKey();
console.log(userAPIKey); // This will print: 1111111111111
class Str {
#uniqueStr;
constructor() {}
set #generateUniqueStringByCustomLength(length = 24) {
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let randomStr = "";
for (let i = 0; i < length; i++) {
const randomNum = Math.floor(Math.random() * characters.length);
randomStr += characters[randomNum];
}
this.#uniqueStr = randomStr;
}
set setRandomString(length) {
this.#generateUniqueStringByCustomLength = length;
}
get #fetchUniqueString() {
return this.#uniqueStr;
}
get getRandomString() {
return this.#fetchUniqueString;
}
}
const str = new Str();
str.setRandomString = 20;
const uniqueStr = str.getRandomString;
console.log(uniqueStr); // This will print a random string everytime you execute the Getter after the Setter.
mise((resolve, reject) => {
// After 500 miliseconds reject the second promise.
setTimeout(() => reject(“The second promise has been rejected.”), 500);
});
(async function () {
try {
const data = await Promise.any([promise1, promise2]);
console.log(data);
} catch (error) {
// If all Promises gets rejected, then this try-catch block will handle
// the aggregate errors.
console.log("Error: ", error);
}
})();
### **逻辑赋值运算符**
- 逻辑 OR 赋值运算符 ||=
- 逻辑与赋值运算符 &&=
- 空合并赋值运算符 ??=
#### **逻辑 OR 赋值运算符**
```js
// 逻辑 OR 赋值运算符 ||= 接受两个操作数,如果左操作数为假,则将右操作数分配给左操作数
// In the example, the ||= will check if the songsCount is false (0).
// If false, then the right value will be assigned to the left variable.
let myPlaylist = {songsCount: 0, songs:[]};
myPlaylist.songsCount ||= 100;
console.log(myPlaylist); // This will print: {songsCount: 100, songs: Array(0)}
a || (a = b)
// 如果左操作数为真,逻辑 AND 赋值运算符 &&= 仅将右操作数分配给左操作数
let myFiles = {filesCount: 100, files:[]};
myFiles.filesCount &&= 5;
console.log(myFiles); // This will print: {filesCount: 5, files: Array(0)}
a && (a = b)
// 如果左操作数为空或未定义,则空合并赋值运算符 ??= 仅将右操作数分配给左操作数。
let userDetails = {firstname: 'Katina', age: 24}
userDetails.lastname ??= 'Dawson';
console.log(userDetails); // This will print: {firstname: 'Katina', age: 24, lastname: 'Dawson'}
a ?? (a = b)
//默认情况下,类方法和属性是公共的,但可以使用哈希 # 前缀创建私有方法和属性。ECMAScript 2021 更新已强制执行隐私封装
class User {
constructor() {}
// The private methods can be created by prepending '#' before
// the method name.
#generateAPIKey() {
return "1111111111111";
}
getAPIKey() {
// The private methods can be accessed by using '#' before
// the method name.
return this.#generateAPIKey();
}
}
const user = new User();
const userAPIKey = user.getAPIKey();
console.log(userAPIKey); // This will print: 1111111111111
class Str {
#uniqueStr;
constructor() {}
set #generateUniqueStringByCustomLength(length = 24) {
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let randomStr = "";
for (let i = 0; i < length; i++) {
const randomNum = Math.floor(Math.random() * characters.length);
randomStr += characters[randomNum];
}
this.#uniqueStr = randomStr;
}
set setRandomString(length) {
this.#generateUniqueStringByCustomLength = length;
}
get #fetchUniqueString() {
return this.#uniqueStr;
}
get getRandomString() {
return this.#fetchUniqueString;
}
}
const str = new Str();
str.setRandomString = 20;
const uniqueStr = str.getRandomString;
console.log(uniqueStr); // This will print a random string everytime you execute the Getter after the Setter.