JavaScript
七个基本类型
-
String
-
Number
-
Boolean
-
Null
-
Undefined
-
Symbol
-
Object
- Array
- Function
基本语法特点
let a = 7 + "2";
let:关键字
a:定义的变量名
=:操作符
对象
var user = {
name:"张三";
yearOfBirth:1998;
calculateAge:function(){
}
}
name:key
"张三":value
function(){}:方法
如何写好JavaScript
写好JS的原则
各司其职:HTML,CSS,JS职能分离
-
HTML/CSS/JS各司其责
-
应当避免不必要的由JS直接操作样式
-
可以用class来表示状态
-
纯展示类交互寻求零 JS方案
-
版本一:JS直接修改了CSS代码
const btn = document.getElementById('modeBtn'); btn.addEventListener('click', (e) => { const body = document.body; if(e.target.innerHTML==='太阳'){ body.style.backgroundColor = 'black'; body.style.color = 'white'; e.target.innerHTML = '月亮'; } else { body.style.backgroundColor = 'white'; body.style.color = 'black'; e.target.innerHTML = '太阳'; } }); -
版本二:各司其职且代码变简短
const btn = document.getElementById('modeBtn'); btn.addEventListener('click', (e) => { const body = document.body; if(body. className != 'night') { body.className = 'night'; } else { body. className = ''; } }); -
版本三:CSS高级用法 只是样式需求不用JS
<body> <input id="modeCheckBox" type="checkbox"> <div class="content"> <header> <label id="modeBtn" for="modeCheckBox"></label>//for一个元素 <h1>深夜食堂</h1> </header> <main> ...... </main> </div> </body>#modeCheckBox : checked + .content{ background-color: black; color: white; transition: all 1s; }
-
组件封装:正确性,扩展性,复用性
基本方法
-
结构设计:HTML
-
展现效果:CSS
-
行为设计
- API(功能)
- Event(控制流):解耦
改进
-
重构:组件插件化
-
解耦:
- 将控制元素抽取成插件
- 插件与组件之间通过依赖注入方式建立联系
-
-
重构:HTML模板化
-
解耦:
- 将HTML模板化,更易于扩展
-
-
抽象化(组件框架 )
- 将组件通用模型抽象出来
过滤抽象:函数式编程
-
用来处理局部细节控制的一些方法
-
函数式编程思想的基础应用
-
高阶函数(HFO)
-
以函数作为参数
-
以函数作为返回值
-
常用于作为函数装饰器
function HOFO(fn) { return function( ... args) { return fn.apply(this, args); } } -
常用高阶函数:
-
Once:为了能够让"只执行一次"的需求覆盖不同的事件处理,我们可以将这个需求剥离出来,这个过程我们称为过程抽象
function once(fn) { return function( ... args) { if(fn) { const ret = fn.apply(this, args); fn = null; return ret; } } } -
Throttle:节流函数
function throttle(fn, time=500) { let timer; return function( ... args) { if(timer == null) { fn.apply(this, args); timer = setTimeout(()=>{ timer = null; },time) } } } -
防抖函数
function debounce(fn, dur) { dur = dur || 100; let timer; return function() { clearTimeout(timer); //永远只会被调用最后一次 timer = setTimeout(()=>{ fn.apply(this, args); },dur) } } -
consumer:把同步的function变成异步的 延时调用
function consumer(fn, time) { let tasks = []; let timer; return function(...args) { tasks.push(fn.bind(this, ...args)); if (timer == null) { timer = setInterval(() => { tasks.shift().call(this); if(tasks.length<=0){ clearInterval(timer); timer = null; } },time); } } } -
iterative:同时操作多个元素 批量操作
const isIterative = obj => obj != null && typeof obj[Symbol.iterator] === 'function'; function iterative(fn) { return function(subject, ...rest) { if (isIterative(subject)) { const ret= []; for(let obj of subject){ ret.push(fn.apply(this, [obj, ...rest])); } return ret; } return fn.apply(this, [subject, ...rest]); } }
-
-
为什么要使用高阶函数
- 抽象和复用:高阶函数允许你抽象出更通用的操作,这些操作可以在不同的上下文中复用。例如,
map、filter和reduce这样的函数都是高阶函数,它们在处理集合或数组时非常有用 - 代码简洁:高阶函数可以帮助你写出更简洁的代码。你不需要为每个特定的操作编写完整的循环或条件逻辑,而是可以依赖高阶函数来处理这些细节
- 模块化:高阶函数促进了代码的模块化。你可以将特定的行为封装在函数中,然后在需要时通过高阶函数来组合这些行为
- 延迟执行:高阶函数可以延迟函数的执行,直到真正需要结果时才调用它们。这在处理异步操作或者需要懒加载的场景中非常有用
- 参数化行为:高阶函数允许你参数化函数的行为。这意味着你可以根据传入的函数参数来改变函数的行为,从而提供更大的灵活性
- 抽象和复用:高阶函数允许你抽象出更通用的操作,这些操作可以在不同的上下文中复用。例如,
-
是纯函数
-
什么是纯函数
-
纯函数是指其返回值仅依赖于其输入参数,且不产生副作用的函数。换句话说,给定相同的输入,纯函数总是返回相同的输出,并且不会对外部状态产生任何影响。
-
特点:
- 确定性:纯函数的输出完全由输入决定,不会受到外部状态或随机因素的影响。
- 无副作用:纯函数不会改变外部状态,不会执行任何 I/O 操作(如读取文件、数据库操作、网络请求等),也不会抛出异常。
- 可预测性:由于纯函数的输出完全由输入决定,因此它们的行为是可预测的,这使得调试和测试变得更加容易。
- 可缓存性:纯函数的输出可以被缓存,因为相同的输入总是产生相同的输出。这意味着如果你多次调用同一个纯函数,你可以存储第一次调用的结果,并在后续调用中返回缓存的结果,从而提高性能。
- 并行性:纯函数可以安全地并行执行,因为它们不会相互干扰。这使得它们在多核处理器和分布式系统中非常有用。
-
-
多使用纯函数可以增加代码的可维护性
-
-
JavaScript拥有命令式和声明式两种编程方式
-
命令式
- 面向过程
- 面向对象
- 强调怎么做
-
let list = [1, 2, 3, 4]; let mapl = []; for(let i = 0; i < list.length; i++) { mapl.push(list[i] * 2); }
-
声明式
- 逻辑式
- 函数式
- 强调做什么
- 具有更强的可拓展性
-
let list = [1, 2, 3, 4]; const double = x => x * 2; list.map(double);
代码质量优化
eg.交通灯状态切换:实现多个交通灯状态切换的功能
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="./01.css">
</head>
<body>
<ul id="traffic" class="light">
<li></li>
<li></li>
<li></li>
</ul>
<script type="module" src="./01.js"></script>
</body>
</html>
#traffic {
display: flex;
flex-direction: column;
}
#traffic li {
display: inline-block;
width: 50px;
height: 50px;
margin: 10px;
background-color: gray;
border-radius: 50%;
}
/* 等待状态 - 黄色 */
#traffic.wait li:nth-child(1) {
background-color: yellow;
}
/* 停止状态 - 红色 */
#traffic.stop li:nth-child(2) {
background-color: red;
}
/* 通过状态 - 绿色 */
#traffic.pass li:nth-child(3) {
background-color: green;
}
-
代码一
const traffic = document.getElementById('traffic'); (function reset() { traffic.className = 'wait'; setTimeout(function() { traffic.className = 'stop'; setTimeout(function() { traffic.className = 'pass'; setTimeout(function() { traffic.className = 'light'; setTimeout(reset, 1000); }, 3000); }, 3000); }, 1000); })(); -
代码二 数据抽象
const traffic = document.getElementById('traffic'); //将数据抽象出来写成一个状态列表 const stateList = [ {state: 'wait', last: 1000}, {state: 'stop', last: 3000}, {state: 'pass', last: 3000},//可以在列表里直接添加新的数据]; function start(traffic, stateList){ //递归调用 function applyState(stateIdx){ const {state, last} = stateList[stateIdx]; //设置成当前状态 traffic.className = state; setTimeout(() => { applyState((stateIdx +1)% stateList.length); }, last) } applyState(0); } start(traffic, stateList); -
代码三 过程抽象 代码过于复杂 过度抽象
const traffic = document.getElementById('traffic'); //wait方法表示等待时间 function wait(time){ return new Promise(resolve => setTimeout(resolve, time)); } //poll方法表示轮循 function poll( ... fnList){ let stateIndex = 0; return async function( ... args){ let fn = fnList[stateIndex++ % fnList.length]; return await fn.apply(this, args); } } //状态方法 async function setState(state, time){ traffic.className = state; await wait(time); } let trafficStatePoll = poll( setState.bind(null, 'wait', 1000), setState.bind(null, 'stop', 3000), setState.bind(null, 'pass', 3000) ); (async function(){ while(1){ await trafficStatePoll(); } })(); -
代码四 异步+函数式
const traffic = document.getElementById('traffic'); function wait(time){ return new Promise(resolve => setTimeout(resolve, time)); } function setState(state){ traffic.className = state; } async function start(){ while(1){ setState('wait'); await wait(1000); setState('stop'); await wait(3000); setState('pass' ); await wait(3000); } } start();
洗牌-生成器
const cards = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
function draw() {
const c = [...cards];
for (let i = c.length; i > 0; i--) {
const cardIndex = Math.floor(Math.random() * i);
[c[cardIndex], c[i - 1] = c[i - 1], c[cardIndex]];
yield c[i - 1];
}
}
const result = draw(cards);
console.log([...result]);
console.log(result.next().value);//只取一张牌
HTML in JavaScript
JSX
是一种JavaScript的语法扩展,它允许你在JavaScript代码中编写类似HTML的标记。JSX实际上是React.createElement()函数的语法糖,它使得在React中编写组件更加直观和方便。
基本语法
JSX的基本语法非常接近HTML,但它有一些特殊的规则:
- JSX必须严格闭合,就像HTML标签一样。
- 你可以把JSX标签当作变量,在任何地方使用它们,甚至可以将它们赋值给变量或将它们放入数组中。
- 自定义组件的首字母必须大写,而内置的HTML标签则不需要。
为什么要使用JSX?
使用JSX的理由包括:
- UI与JavaScript逻辑的融合:JSX允许你将UI(用户界面)与JavaScript逻辑结合在一起,这使得开发体验更好,尤其是在React中。
- 错误和提示:使用JSX可以让React显示更多有用的错误和警告消息,帮助你更有效地调试代码。
- 动态内容展示:JSX支持在JSX中嵌入JavaScript表达式,通过大括号
{}包裹,这对于动态内容展示非常有用。 - 条件渲染:你可以在JSX中使用JavaScript表达式实现条件渲染,例如使用三元运算符或逻辑与
&&。
在JSX中嵌入表达式
在JSX中,你可以这样嵌入JavaScript表达式:
const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;
属性传递
在JSX中传递属性非常简单,支持JavaScript表达式:
const element = <img src="logo.png" alt="Logo" />;
const greeting = <h1>Hello, {user.name}!</h1>;
事件处理
JSX支持直接绑定事件,通过onClick、onChange等属性传递事件处理函数:
function handleClick() {
alert("Button clicked!");
}
const button = <button onClick={handleClick}>Click me</button>;
样式和类名
在JSX中,className用于代替HTML中的class属性。内联样式则使用对象的形式,属性名遵循camelCase规则:
const element = <div className="container">Content</div>;
const style = { color: "blue", fontSize: "20px" };
const element = <h1 style={style}>Styled Text</h1>;
数组渲染
可以通过map()方法遍历数组生成JSX元素列表。在渲染列表时,为每个元素添加key属性,以提高渲染效率:
const items = ["Apple", "Banana", "Cherry"];
const list = (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
JSX是一种强大的工具,它使得在React中构建用户界面变得更加直观和高效。通过上述信息,你可以了解到JSX的基本用法和一些关键特性。