JavaScript设计模式
call、apply、bind 模拟实现
async 、await、Generator 原理实现
Promise 学习笔记
JS 类的创建继承 与 new原理实现
防抖、节流 和 预加载、懒加载
number、boolean、string、null、undefined、symbol
基本数据类型是以名值得形式存储在栈内存中的。
进行赋值操作时会新开辟一片栈内存存储新的名值。
数组、对象、函数等
以上的类型会在栈内存和堆内存中分别开辟一片空间进行存储。
当直接赋值时其实是将a的堆地址赋值给了b,两者最终指向了同一个堆内存。这就是浅拷贝,带来的后果就是你在对b的元素进行操作时,同时改变了a对应的值。
第一种方法简单粗暴,使用JSON.stringify和JSON.parse进行两次转换。
let a = [1,3,5,7];
let b = JSON.parse(JSON.stringify(a));
b[0] = 99;
console.log("a", a); // [1,3,5,7]
console.log("b", b); // [99,3,5,7]
这种方法存在一种很大的缺点,转换时会自动忽略undefined,Symbol、function
用递归的方法去遍历复制所有的层级
function deepClone(obj){
// 判断数据形式
let clone = Array.isArray(obj)?[]:{};
if(obj && typeof obj === "object"){
for(let key in obj){
if(obj.hasOwnProperty(key)){
// 属性是对象则进行递归
if(obj[key] && typeof obj[key] === "object"){
clone[key] = deepClone(obj[key]);
}else{
clone[key] = obj[key];
}
}
}
}
return clone;
}
let a = [1,3,5,7],
b = deepClone(a);
a[0] = 999;
console.log(a); // [1,3,5,7]
console.log(b); // [999,3,5,7]
var arr = [1, 1, "true", "true", true, 15, false]
//利用ES6去重
function unique(arr) {
return Array.from(new Set(arr))
}
//利用indexOf方法(该方法用于返回指定数组元素首次出现的地方,若没有则返回-1)
function unique(arr) {
if(!Array.isArray(arr)) {
console.log("error");
return ;
}
let result = [];
for (let i = 0; i < arr.length; i ++) {
if (result.indexOf(arr[i]) == -1) {
result.push(arr[i])
}
}
return result;
}
//利用对象属性不能相等
function unique(arr) {
if (! Array.isArray(arr)) {
return
}
let result = [];
let obj = {};
for (let i = 0; i < arr.length; i ++) {
if (!obj[arr[i]]) {
result.push(arr[i])
obj[arr[i]] = 1;
} else {
obj[arr[i]] ++
}
}
return array;
}
//使用Promise 先输出111,延迟500ms后输出222
function sleep(ms) {
return new Promise((resolve) => {
console.log("111");
setTimeout(resolve,ms)
})
}
sleep(500).then(function(){
console.log("222")
})
//使用async/await 过了500ms后才输出111
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve,ms)
})
}
async function test() {
let temp = await sleep(500);
console.log("111");
return temp;
}
//写一个函数
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i)
},1000*i)
}
for(var i = 0; i < 5; i ++) {
(function(i){
setTimeout(function(){
console.log(i);
},1000*i)
})(i)
}
function sleep(interval){
return new Promise((resolve)=>
setTimeout(resolve);
}, interval);
}
async function stepPrint(n){
for(let i=0;i<=n;i++){
console.log(i);
await sleep(i*1000);
}
}
stepPrint(5)
class Node{
constructor(data) {
this.data = data;
this.next = null;
}
}
class LinkList{
constructor() {
this.head = new Node('head');
}
findByValue = (value) => {
let currentNode = this.head;
while (currentNode !== null && currentNode.data !== value) {
currentNode = currentNode.next;
}
return currentNode === null ? -1 : currentNode;
}
findByIndex = (index) => {
let pos = 0;
let currentNode = this.head;
while (currentNode !== null && pos !== index) {
pos ++;
currentNode = currentNode.next;
}
return currentNode === null ? -1 : currentNode;
}
insert = (value, element) => {
let currentNode = this.findByValue(element);
if (currentNode == -1) {
console.log('error');
return;
}
let newNode = new Node(value);
newNode.next = currentNode.next;
currentNode.next = newNode;
}
delete = (value) {
let currentNode = this.head;
preNode = null;
while (currentNode !== null && currentNode.data !== value) {
preNode = currentNode;
currentNode = currentNode.next;
}
if (currentNode == null) {
return -1
}
preNode.next = currentNode.next;
}
print = () => {
let currentNode = this.head
while (currentNode !== null) {
console.log(currentNode.data)
currentNode = currentNode.next;
}
}
}
function p(url){
let json;
let s = document.createElement('script');
s.src = url + '?callback=fn';
window.fn = function(data){
json = data;
}
//当script被插入文档中时,src中的资源就会开始加载
document.body.appendChild(s);
return new Promise((resolve,reject)=>{
/* throw('err in promise'); */
s.onload = function(e){
resolve(json);
}
s.onerror = function(){
reject(json);
}
});
}
p('http://localhost:8082').then(data=>{
console.log(data);
throw('err before then');
}).catch(err => {
//可以捕捉到then里的err befor then也可以捕捉到new Promise里的err in promise。
console.log(err)
var myNewAjax=function(url) {
return new Promise(function(resolve,reject){
var xhr = new XMLHttpRequest();
xhr.open('get',url);
xhr.send(data);
xhr.onreadystatechange=function(){
if(xhr.status==200&&readyState==4){
var json=JSON.parse(xhr.responseText);
resolve(json)
}else if(xhr.readyState==4 &&xhr.status!= 200){
reject('error');
}
}
})
}
//for...in...遍历属性
function judgeObj(obj) {
for (var attr in obj) {
return alert("非空对象")
}
return alert("空对象")
}
//JSON自带的stringify()方法
if(JSON.stringify(obj) == "{}") {
console.log("空对象")
}
//ES6新增的方法Object.keys()
if(Object.keys(obj).length > 0) {//会转化为一个数组
console.log("非空对象")
}
function People(){
25 var name='张三'; // 私有变量; 外部无法访问
27 function say(){ // 私有函数;
28 return '我是......';
29 }
31 this.getName=function(){ // 对外公共的特权方法; 外部可以访问
32 return name;
33 }
38 }
39 var p=new People()
40 alert(p.getname())
var keys= Object.keys(testObj);
console.log(keys); // 输出 keys ["name", "age", "action"]
Object.getOwnPropertyNames():
方法返回一个指定对象所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组.(不可枚举: 比如属性是一个js方法) var keys = Object.getOwnPropertyNames(testObj);
console.log(keys); // 输出 keys ["name", "age", "action"]
var keys =[];
for(var i in testObj){
keys.push(i);
}
console.log(keys); // keys ["name", "age", "action"]
function log(){
console.log.apply(console, arguments);
};
log(1); //1
log(1,2); //1 2
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<div class="imgBox">
<img class="img-slide img1" src="images/1.png" alt="1">
<img class="img-slice img2" src="images/2.png" alt="2">
<img class="img-slice img3" src="images/3.png" alt="3">
</div>
<style>
.img1{
display:block;
}
.img2{
display: none;
}
.img3{
display: none;
}
</style>
<script type="text/javascript">
var index = 0;
function changeImg() {
index ++;
var a = document.getElementsByClassName("img-slice");
if (index >= a.length) {
index = 0;
}
for (let i = 0; i < a.length; i ++) {
a[i].style.display = "none";
}
a[index].style.display = "block";
}
setInterval(changeImg, 2000)
</script>
</body>
</html>
https://www.jianshu.com/p/366e374e108d
https://blog.csdn.net/qq_23244029/article/details/93517575
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>实现Tab组件title>
<link rel="stylesheet" type="text/css" href="tab.css">
head>
<body>
<div id="container1">
<ul class="tab-list">
<li class="tab-item" href="panel-1">tab1li>
<li class="tab-item" href="panel-2">tab2li>
<li class="tab-item" href="panel-3">tab3li>
ul>
<div class="panel active" id="panel-1">content1div>
<div class="panel" id="panel-2">content2div>
<div class="panel" id="panel-3">content3div>
div>
<script>
/**
* Tab 组件
* @param {String} containerId 容器Id
*/
function Tab(containerId)
{
var cont1 = document.getElementById(containerId);
var tab_items = cont1.getElementsByClassName('tab-item');
var pls = cont1.getElementsByClassName('panel');
for(let i = 0;i < tab_items.length;i++){
tab_items[i].onclick = function(e){
console.log(e);
for(let j = 0;j<tab_items.length;j++){
if(i == j){
pls[i].style.display = "block";
}else{
pls[j].style.display = "none";
}
}
}
}
}
/**
* active 方法,可以控制第几个 Tab 组件显示
* @param {Number} index 要显示的 tab 的序号,从0开始
*/
Tab.prototype.active = function (index)
{
}
var tab = new Tab('container1');
script>
body>
html>
js拖拽功能的实现
https://blog.csdn.net/weixin_44462907/article/details/88756890
let loadImg = (src) => {
return new Promise((resolve, reject) => {
let img = document.createElement('img')
img.src = src
document.body.append(img)
setTimeout(() => {
resolve(true)
}, 1000)
})
}
const imgs = ['../src/img/1.PNG', '../src/img/1.PNG', '../src/img/1.PNG'];
// 依次加载图片
async function fSync(imgs) {
for (let i of imgs) {
await loadImg(i)
}
}
fSync(imgs);