JS設計模式
JavaScript設計模式
apply、call、bind
call、apply、bind 模拟實作
async await generator
async 、await、Generator 原理實作
Promise 實作
Promise 學習筆記
類的建立與繼承 new實作
JS 類的建立繼承 與 new原理實作
防抖、節流 和 預加載、懶加載
防抖、節流 和 預加載、懶加載
深淺拷貝
1. 資料類型
基本資料類型
number、boolean、string、null、undefined、symbol
基本資料類型是以名值得形式存儲在棧記憶體中的。
進行指派操作時會新開辟一片棧記憶體存儲新的名值。
引用資料類型
數組、對象、函數等
以上的類型會在棧記憶體和堆記憶體中分别開辟一片空間進行存儲。
當直接指派時其實是将a的堆位址指派給了b,兩者最終指向了同一個堆記憶體。這就是淺拷貝,帶來的後果就是你在對b的元素進行操作時,同時改變了a對應的值。
2. 深拷貝方法
方法一
第一種方法簡單粗暴,使用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;
}
實作sleep的效果
//使用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)
}
用promise和async實作每間隔1s,2s,3s…列印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;
}
}
}
基于promise實作jsonp
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)
将原生的ajax封裝成promise
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("非空對象")
}
如何實作一個私有變量,用getName方法可以通路,不能直接通路
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())
獲得對象上的屬性
- 對象内置屬性方法:Object.keys();該方法傳回一個數組,數組内包括對象内可枚舉屬性以及方法名稱。
var keys= Object.keys(testObj);
console.log(keys); // 輸出 keys ["name", "age", "action"]
-
方法傳回一個指定對象所有自身屬性的屬性名(包括不可枚舉屬性但不包括Symbol值作為名稱的屬性)組成的數組.(不可枚舉: 比如屬性是一個js方法)Object.getOwnPropertyNames():
var keys = Object.getOwnPropertyNames(testObj);
console.log(keys); // 輸出 keys ["name", "age", "action"]
- 最原始的 for…in 循環。
var keys =[];
for(var i in testObj){
keys.push(i);
}
console.log(keys); // keys ["name", "age", "action"]
定義一個log方法
function log(){
console.log.apply(console, arguments);
};
log(1); //1
log(1,2); //1 2
JavaScript中實作輪播
<!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
實作一個tab元件
https://blog.csdn.net/qq_23244029/article/details/93517575
<!DOCTYPE html>
<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">tab1</li>
<li class="tab-item" href="panel-2">tab2</li>
<li class="tab-item" href="panel-3">tab3</li>
</ul>
<div class="panel active" id="panel-1">content1</div>
<div class="panel" id="panel-2">content2</div>
<div class="panel" id="panel-3">content3</div>
</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拖拽功能的實作
js拖拽功能的實作
(三)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);