58同城成都网站建设,视频直播网站怎么做,wordpress排版Markdown,120平米花6万装修效果图JS基础讲解
9.1、JS基础语法
JavaScript 是一种用于在客户端#xff08;即用户的浏览器#xff09;上运行的编程语言。它是一种脚本语言#xff0c;可以直接嵌入到 HTML 页面中#xff0c;并由浏览器解释和执行。
在客户端环境中#xff0c;JavaScript 可以与用户交互即用户的浏览器上运行的编程语言。它是一种脚本语言可以直接嵌入到 HTML 页面中并由浏览器解释和执行。
在客户端环境中JavaScript 可以与用户交互操作和修改网页的内容、结构和样式。它可以用于处理用户输入、响应事件、进行表单验证、创建动态效果等。JavaScript 还可以通过浏览器提供的 API 访问浏览器功能例如操作 DOM文档对象模型、发送网络请求、处理本地存储等。
需要注意的是JavaScript 也可以在服务器端运行例如使用 Node.js 环境。在服务器端JavaScript 可以用于构建网络应用、处理后端逻辑等。但在这种情况下它并不是典型的“客户端语言”而是作为一种通用的脚本语言使用。
from flask import Flask, render_templateapp Flask(__name__, template_foldertemplates, static_folderstatic)app.get(/index)
def index():return render_template(index.html)app.run()
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/titlestyleh3 {color: green;}/style/head
bodyh3hello Alex/h3script src/static/a.js/script/body
/html【1】基本语法
// JS代码导入方式
// 1 直接编写/*scriptconsole.log(hello yuan)/script*/
// 2 导入文件// script srchello.js/script// 单行注释
/*这是多行注释*/// 语句分隔符 ; 表示一行代码的结束【2】变量与数据类型
// (1) 声明变量
var x; // 声明一个变量叫x, x没有值. 此时打印x的内容是undefined(没有被定义)// 对x进行打印看看效果.
// 在控制台记录xxxx python中的print()
// 查看打印的内容在F12 - Console - 可以看到打印的内容console.log(x);// (2) 基本数据类型number string boolvar x 3.1415; // 声明变量x, 并且给x一个初始值. 123
console.log(typeof x); // 可以查看数据类型. 但是只能看基础数据类型.var x hello yuan;
console.log(typeof x); // string 字符串var x1 true;
var x2 false; // 布尔值. python里面是大写的. js里面是小写.console.log(typeof x1); // boolean 布尔. python简化成bool// (3) 高级数据类型 数组[] 对象{} var x [1,2,3]; // 数组. python的列表.
console.log(typeof x); // 类型叫objectvar x {name:yuan,age:22}; // 对象 python的字典.
console.log(typeof x); // 也是object// (4) 两个特殊值: undefined nullvar x; // undefined
console.log(typeof x); // undefined类型... 不占用内存空间的var x null; // 空.... 是python的None, 要使用堆内存的....
console.log(typeof x); // object类型// 一次性可以声明多个变量
var nameyuan, age20, joblecturer;
var a, b, c3, d, e 5; // 从左到右,声明5个变量, 其中, c3, e5
类型转换
// 在js中. 所有的数据和字符串相加. 结果都是字符串拼接.(重点)
var a 123;
var b 我爱你;
console.log(a b);
console.log(11); // 2var a 123; // 字符串
// 字符串转化成整数
// parse 转换
// Int 整数
a parseInt(a);
console.log(a 3); // 126 数学上的加法. 证明转化成功了.var a 123; // 转化成字符串
var b a.toString(); // 把数字, 转化成字符串
console.log(b 3); //1233// 一般的程序员不用toString()的.
var a 123;
var b a ; // 在逆向的过程中. 这种写法是最多的.
console.log(b333); // 123333 字符串var a 123;
// 数字的toString()可以指定进制
var b a.toString(16);
console.log(b);var m 7b; // 眼睛看着是字符串. 但是我们知道它应该是一个十六进制的字符串.
// 字符串, 转化成 整数 parseInt
var n parseInt(m, 16);
console.log(n)【3】运算符
// 1 科学运算符 - * / %// 2比较运算符!// 3 赋值运算符 - * / // 在单独使用a和a是没有区别的. 都是让a自增1
var b a ; // 先赋值, 后运算...console.log(a); // 11
console.log(b); // 10var b a; // 先计算, 后赋值
console.log(a);
console.log(b);// 4逻辑运算符 Python中的and, or, not
// , 并且, 左右两端必须同时为真, 结果才能是真..
// ||, 或者, 左右两端, 有一个是真, 结果就是真
// !, 非/不, 非真即假, 非假既真.console.log(1 2 || 3 5);
console.log(1 2 3 5);console.log(!true);
console.log(!false);// x() y()
// 该逻辑叫短路...如果前面的表达式已经得到结果了. 后面就不运行了. 相同的逻辑还有||
// 如果x()返回真. 则运行y()
// 如果x()返回假, 则不运行y(). 直接结束判断了.// 5逗号运算符
a 1,2,3,4
b (1,yuan,true)
// 6三目运算条件? 成立: 不成立
// 案例1
var a 100;
var b 20;
var c a b ? a: b;
console.log(c);
// 案例2:终极一练let a 10;
let b 20;
let c 5;
let d 17;let e;
let m;
e (e a 3 ? b : c, m e b ? c-- : a 3 b % d ? 27: 37, m);
// e a 3 ? b : c; // e 20
// b 21 , m 和 a都是37
// m e b ? c-- : a 3 b % d ? 27: 37;
// e m; // e 37 m 38 a 37【4】流程控制语句
分支语句
// 分支语句
if(条件){// 条件为true时,执行的代码}else{// 条件为false时,执行的代码} switch(条件){case 结果1:// 满足条件执行的结果是结果1时,执行这里的代码..break;case 结果2:// 满足条件执行的结果是结果2时,执行这里的代码..break;...default:// 条件和上述所有结果都不相等时,则执行这里的代码}// 1双分支
var age 23
if (age 18) {console.log(播放成人电影)
} else {console.log(播放未成年电影)
}// 2多分支
var score 45;
if (score 90) {console.log(A);
} else if (score 80) {console.log(B);
} else if (score 70) {console.log(C);
} else if (score 60) {console.log(D);
} else {console.log(E);
}// 3switch多分支
var week 3;
switch(week){case 1:console.log(星期一);break;case 2:console.log(星期二);break;case 3: // 某一个case匹配成功. 那么后面的case就不判断了, 直接被执行.console.log(星期三);break;case 4:console.log(星期四);break;case 5:console.log(星期五);break;case 6:console.log(星期六);break;case 7:console.log(星期天);break;default:console.log(啥也不是!);break;
}循环语句
/*// 循环语句
while(循环的条件){// 循环条件为true的时候,会执行这里的代码}// 循环三要素
for(1.声明循环的开始; 2.条件; 4.循环的计数){// 3. 循环条件为true的时候,会执行这里的代码
} * 1. 首先, 会执行语句1, 通常会在语句1里完成对循环变量的初始化* 2. 然后, 判断表达式2计算的结果是否是真, 如果是真, 则执行循环体, 如果是假, 结束循环* 3. 执行完循环体后. 执行表达式3然后回到第二步...*/// while 循环
var a 0; // 1. 初始变量
while (a 100) { // 2. 条件判断console.log(我爱你); // 业务需求...循环内容...a; // 3. 步进语句
}for(var i 0; i 10; i){console.log(i);
}
【5】字符串对象
// js的字符串对象
var s Hello Yuan
console.log(s.toUpperCase())
console.log(s.toLowerCase())
console.log(s.slice(0, 5))
console.log(s.split( )) // [Hello,Yuan]
console.log(s.length)
console.log(s.trim( ).length)
console.log(s.trimEnd( ).length)
console.log(s.indexOf(Yuan))
console.log(s.replace(Yuan,Rain))
console.log(s.startsWith(Hel))【6】数组
// 注意, 前端js里面的数组. 相当于python的列表, java的List// 创建数组的方法;
// 1. 直接赋值一个数组
var arr1 [11,22,33];
console.log(arr1);// new表示创建对象. 理解成分配内存.
var arr2 new Array(); // var arr2 []// 1. push 在数组的末尾添加数据...
// 2. pop 在数组的末尾删除数据
var arr [11,22,33,44];
arr.push(55);
var item arr.pop();
console.log(item);// 1 unshift 在数组的首位添加数据... 2 shift 删除数组的首位数据var arr [11,22,33];
arr.unshift(0); // 在数组的前面插入数据
// console.log(arr);
var item arr.shift();
console.log(item);
console.log(arr);var arr [a,b,c];
arr.splice(1,1);
arr.splice(1,0,b)
arr.splice(1,1,B)arr.reverse();// slice(开始下标,结束下标) 切片,开区间
arr.slice(1,3)var arr [北京,深圳,广州];
console.log(arr.join(,)); // 把数组转化成字符串// 循环和遍历
// key 0 1 2 3 4 5
var arr [朱元璋, 朱允炆, 朱棣, 朱高炽, 朱高煦, 朱瞻基];// 三要素for循环
for(var i 0; i arr.length; i){console.log(arr[i]);
}// for-in
for(var x in arr){ // 此时拿到的是数组的索引(key)console.log(x);
}// for-of
for (var x of arr){ // 此时拿到的是数组的元素(value)console.log(x);
}// arr中的每一个元素执行里面传递进去的函数
// 回调函数的参数是 元素和索引console.log(ret);
【7】对象
var obj {name: yuan,age: 18,girl_friend: {name: 高圆圆,age: 28}}// 当他是python的字典, 无缝衔接的. [] 也可以翻译成的
console.log(obj[girl_friend][name]);
// 当他是对象... 对象.属性 .可以翻译成的
console.log(obj.name)
console.log(obj.girl_friend.name)// 它俩可以混着来.
var w girl_friend
console.log(obj[w].name);
console.log(obj.girl_friend[name]);
// js的对象在使用的时候. 既可以通过[]来获取属性的值. 也可以通过.来获取属性的值
// 区别: []里面必须放字符串.
// .后面放的必须是属性名(不可以是字符串)
console.log(obj.girl_friend.name); // 68// 如果想要对代码进行伪装,混淆. 就不能用.console.log(obj[girl_friend][name]); // 高圆圆
console.log(obj.girl_friend.name); // 高圆圆var obj {};
obj.name alvin; // 对象.属性 值. 可以给对象增加新的属性(设置一个新的属性)
obj[age] 28;console.log(obj);序列化和反序列化
方法描述JSON.stringify(obj)把obj对象转换成json格式字符串会移除对象方法JSON.parse(str)把符合json语法的字符串转换成js对象
【8】其它常用对象
// Math对象 Date类
var nownew Date();
console.log(now.toLocaleString( ));// console.log(Math.random());
console.log( Math.round(Math.random() * 10 ));9.2、函数
【1】函数初识
// 函数声明
function 函数名(形参){return // 返回值
}// 函数调用
函数名(实参)// 编译运行
// 默认返回undefined
// arguments参数
【2】匿名函数
在 JavaScript 中匿名函数是一种没有名称的函数定义。匿名函数可以被直接传递给其他函数作为参数也可以被赋值给变量或对象的属性以便稍后调用。
// 匿名函数赋值变量var foo function () {console.log(这是一个匿名函数)};// 匿名函数的自执行
(function (x,y) {console.log(xy);})(2,3)// 匿名函数作为一个高阶函数使用
function bar() {return function () {console.log(inner函数)}
}bar()()匿名函数常用于回调函数、事件处理程序、异步操作等场景它们允许我们在需要时动态定义函数逻辑并将其作为值传递或存储而不需要为函数命名。这提供了更灵活和简洁的编程方式。
【3】作用域
作用域Scope是指在程序中定义变量的可访问性和可见性的范围。它决定了在代码中的哪些位置可以访问或引用特定变量、函数或对象。
在大多数编程语言中包括 JavaScript在不同的作用域中定义的变量具有不同的可见性和生命周期。常见的作用域类型有以下几种
全局作用域Global Scope全局作用域是在整个程序中都可访问的作用域。在全局作用域中声明的变量可以在程序的任何位置被访问。函数作用域Function Scope函数作用域是在函数内部定义的作用域。在函数作用域中声明的变量只能在函数内部被访问它们对于函数外部是不可见的。每当函数被调用时都会创建一个新的函数作用域。块级作用域Block Scope块级作用域是在代码块通常由花括号 {} 包围内定义的作用域。在块级作用域中声明的变量只能在该块内部被访问而在块外部是不可见的。在 ES6 中引入的 let 和 const 关键字可以用来创建块级作用域。
// 首先熟悉下varvar name yuan; // 声明一个全局变量 name并赋值”yuan“
name 张三; // 对已经存在的变量name重新赋值 ”张三“
console.log(name);age 18 // 之前不存在age变量这里等同于var age 19 即声明全局变量age并赋值为18var gender male
var gender female // 原内存释放与新内存开辟指针指向新开辟的内存
console.log(gender)作用域案例
var num 10; // 在函数外部声明的变量, 全局变量
function func(){// num 20; // 函数内部直接使用变量,则默认调用了全局的变量,//var num 20; console.log(函数内部num,num)
}
func();
console.log(全局num,num);作用域的正确使用可以避免变量名冲突和数据泄漏并提供更好的代码封装和隔离性。理解作用域的概念对于编写可维护和可扩展的代码非常重要。
【4】闭包函数
闭包closures是 Javascript 语言的一个难点也是它的特色很多高级应用都是依靠闭包实现的。闭包与变量的作用域以及变量的生命周期密切相关本节我们就来简单介绍一下。 在计算机科学中闭包英语Closure又称词法闭包Lexical Closure或函数闭包function closures是引用了自由变量外部非全局的函数。 简单来说就是一个函数定义中引用了函数外定义的变量并且该函数可以在其定义环境外被执行。这样的一个函数我们称之为闭包函数。
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/titlescriptfunction getCounter() {var count 0function counter() {var name yuancount // count count1console.log(count)}// counter()// counter()// counter()return counter}c1 getCounter()c1()c1()c2 getCounter()c2()c2()/scriptscriptvar count 100/script
/head
bodybutton onclickc1()add1/button
button onclickc2()add2/button
/body
/html9.3 、Window对象
window 是客户端浏览器对象模型的基类window 对象是客户端 JavaScript 的全局对象。一个 window 对象实际上就是一个独立的窗口对于框架页面来说浏览器窗口每个框架都包含一个 window 对象。
1全局作用域
在客户端浏览器中window 对象是访问 BOM 的接口如引用 document 对象的 document 属性引用自身的 window 和 self 属性等。同时 window 也为客户端 JavaScript 提供全局作用域。
由于 window 是全局对象因此所有的全局变量都被解析为该对象的属性。
scriptvar username yuanhao; //全局变量function f() { //全局函数console.log(username);}console.log(window.username); //返回字符串“yuanhao”window.f(); //返回字符串“yuanhao”/script
2使用系统对话框
window 对象定义了 3 个人机交互的方法主要方便对 JavaScript 代码进行调试。
alert()确定提示框。由浏览器向用户弹出提示性信息。该方法包含一个可选的提示信息参数。如果没有指定参数则弹出一个空的对话框。confirm()选择提示框。。由浏览器向用户弹出提示性信息弹出的对话框中包含两个按钮分别表示“确定”和“取消”按钮。如果点击“确定”按钮则该方法将返回 true单击“取消”按钮则返回 false。confirm() 方法也包含一个可选的提示信息参数如果没有指定参数则弹出一个空的对话框。prompt()输入提示框。可以接收用户输入的信息并返回输入的信息。prompt() 方法也包含一个可选的提示信息参数如果没有指定参数则弹出一个没有提示信息的输入文本对话框。
3访问客户端对象
使用 window 对象可以访问客户端其他对象这种关系构成浏览器对象模型window 对象代表根节点浏览器对象关系的关系如图所示每个对象说明如下。
window客户端 JavaScript 顶层对象。每当 或 标签出现时window 对象就会被自动创建。navigator包含客户端有关浏览器信息。screen包含客户端屏幕的信息。history包含浏览器窗口访问过的 URL 信息。location包含当前网页文档的 URL 信息。document包含整个 HTML 文档可被用来访问文档内容及其所有页面元素。
4使用定时器
window 对象包含 4 个定时器专用方法说明如下表所示使用它们可以实现代码定时执行或者延迟执行使用定时器可以设计演示动画。
方法说明setInterval()按照执行的周期单位为毫秒调用函数或计算表达式setTimeout()在指定的毫秒数后调用函数或计算表达式clearInterval()取消由 setInterval() 方法生成的定时器clearTimeout()取消由 setTimeout() 方法生成的定时器
setTimeout() 方法能够在指定的时间段后执行特定代码。用法如下
var o setTimeout(code, delay)
参数 code 表示要延迟执行的字符串型代码将在 Windows 环境中执行如果包含多个语句应该使用分号进行分隔。delay 表示延迟时间以毫秒为单位。
该方法返回值是一个 Timer ID这个 ID 编号指向延迟执行的代码控制句柄。如果把这个句柄传递给 clearTimeout() 方法则会取消代码的延迟执行。
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
bodyinput idID1 typetext
button onclickbegin()开始/button
button onclickend()停止/buttonscriptfunction showTime(){var nowd2new Date().toLocaleString();var tempdocument.getElementById(ID1);temp.valuenowd2;}var ID;function begin(){if (IDundefined){showTime();IDsetInterval(showTime,1000);}}function end(){clearInterval(ID);IDundefined;}/script/body
/html9.4、jQuery
jQuery是一个快速、简洁的JavaScript框架是继Prototype之后又一个优秀的JavaScript代码库或JavaScript框架。jQuery设计的宗旨是“write LessDo More”即倡导写更少的代码做更多的事情。它封装JavaScript常用的功能代码提供一种简便的JavaScript设计模式优化HTML文档操作、事件处理、动画设计和Ajax交互。
jQuery的核心特性可以总结为具有独特的链式语法和短小清晰的多功能接口具有高效灵活的css选择器并且可对CSS选择器进行扩展拥有便捷的插件扩展机制和丰富的插件。jQuery兼容各种主流浏览器如IE 6.0、FF 1.5、Safari 2.0、Opera 9.0等
目前在市场上, 1.x , 2.x, 3.x 功能的完善在1.x, 2.x的时候是属于删除旧代码,去除对于旧的浏览器兼容代码。3.x的时候增加es的新特性以及调整核心代码的结构
根本上jquery就是一个写好的js文件,所以想要使用jQuery的语法必须先引入到本地
script srchttps://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js/script查找标签
/*
基本选择器 :$(#id)
$(.class)
$(element)
$(.class,p,div)后代选择器
$(.outer div) 筛选器$().first() $().last() $().eq(2) 导航查找 $(div).children(.test)
$(div).find(.test) // 向下查找兄弟标签
$(.test).next() // 查找所有兄弟标签
$(div).siblings() // 查找父标签
$(.test).parent() */绑定事件
// 绑定事件
$().on(事件名,匿名函数)
// $().click()操作标签
文本操作
$(选择符).html() // 读取指定元素的内容,如果$()函数获取了有多个元素,提取第一个元素
$(选择符).html(内容) // 修改内容,如果$()函数获取了多个元素, 则批量修改内容value操作
$().val()属性操作
//读取属性值$(选择符).attr(属性名); // 获取非表单元素的属性值,只会提取第一个元素的属性值
//操作属性$(选择符).attr(属性名,属性值); // 修改非表单元素的属性值,如果元素有多个,则全部修改css样式操作
// 操作样式
$().css(样式属性,样式值)class 属性操作
$().addClass(class1 class2 ... ...) // 给获取到的所有元素添加指定class样式
$().removeClass() // 给获取到的所有元素删除指定class样式
$().toggleClass() // 给获取到的所有元素进行判断,如果拥有指定class样式的则删除,如果没有Ajax请求
Ajax一般中文称之为“阿贾克斯”是英文 “Async Javascript And Xml”的简写译作异步js和xml传输数据技术。
ajax的作用 ajax可以让js代替浏览器向后端程序发送**http**请求与后端通信在用户不知道的情况下操作数据和信息从而实现页面局部刷新数据/无刷新更新数据。
所以开发中ajax是很常用的技术主要用于操作后端提供的数据接口从而实现网站的前后端分离。
ajax技术的原理是实例化js的XMLHttpRequest对象使用此对象提供的内置方法就可以与后端进行数据通信。
数据接口
数据接口也叫api接口表示后端提供操作数据/功能的url地址给客户端使用。
客户端通过发起请求向服务端提供的url地址申请操作数据【操作一般增删查改】
同时在工作中大部分数据接口都不是手写而是通过函数库/框架来生成。
ajax的使用
ajax的使用必须与服务端程序配合使用但是开发中我们对于ajax请求的数据不仅仅可以是自己写的服务端代码也可以是别人写好的数据接口进行调用。
数据接口
# 天气接口
https://v0.yiketianqi.com/api?unescape1versionv91appid43656176appsecretI42og6Lmextcityidcity# 音乐接口
https://c.y.qq.com/v8/fcg-bin/fcg_v8_toplist_cp.fcg?g_tk5381uin0formatjsoninCharsetutf-8outCharsetutf-8%C2%ACice0platformh5needNewCode1tpl3pagedetailtypetoptopid36_1520777874472%E4%BD%9C%E8%80%85%EF%BC%9Atsia%E9%93%BE%E6%8E%A5%EF%BC%9Ahttps://www.jianshu.com/p/67e4bd47d9819.5、JS进阶
【1】原型对象prototype
案例1:
// 创建方式1
var foo new Function(console.log(hello world!))
foo()// 创建方式2
function Person() {console.log(hello person)
}var p1 Person()
console.log(p1)var p2 new Person()
console.log(p2)什么是JS原型对象? prototype(原型对象)就是一个容器. {}存放公共的方法给对象使用.对象可以直接访问原型对象中的方法和属性.原型对象类似Python的类对象fn.prototype 原型对象和函数之间的关系. 每个函数都会有一个prototype属性,指向原型对象.每个原型对象都会有一个constructor属性,指向函数.总结:每个函数与原型对象之间的关系是互相引用. 对象和原型对象和函数之间的关系 函数创建对象var o new Fn();对象通过__proto__属性,指向原型对象.对象可以直接调用原型对象中所有的属性和方法.对象可以通过原型对象中的constructor属性知道构造函数总结: 原型对象就是一个容器,帮助函数存放公共方法,以及给函数new出来的对象提供公共方法使用. function Dog(name, age) {this.name name;//面试题构造函数中的this指向谁 答指向new创建的对象this.age age;this.sleep function () {console.log(sleeping)}}// Dog(rain,12) // 普通函数
//构造函数
let alex new Dog(alex, 36); // 使用new来创建对象
let eric new Dog(eric, 35); // 使用new来创建对象// (1) 函数对象通过prototype容器设置公共属性和方法
Dog.prototype.eat function (food) {console.log(this.name 吃 food);
}alex.eat(吃骨头)
eric.eat(吃肉)// (2) 对象通过__proto__属性,指向原型对象
console.log(alex.__proto__)
console.log(alex.__proto__.constructor.name)
console.log(alex.__proto__.constructor)// 看看能不能理解
console.log(alex.__proto__ Dog.prototype)
console.log(Dog.prototype)alex.age 100
console.log(alex.age) // 先查找自己的空间找不到去原型中找
console.log(eric.age)// 猜一猜1
Dog.prototype.sleep function (){console.log(prototype sleeping)
}alex.sleep()// 猜一猜2
let zhangSan new Dog(张三, 35);
Dog.prototype {fly:function (){console.log(flying...)}
}
// let zhangSan new Dog(张三, 35);
// zhangSan.fly()
zhangSan.eat(辣条)
【2】call和apply方法
callapply都属于Function.prototype的一个方法它是JavaScript引擎内在实现的因为属于Function.prototype所以每个Function对象实例(就是每个方法)都有callapply属性。既然作为方法的属性那它们的使用就当然是针对方法的了这两个方法是容易混淆的因为它们的作用一样只是使用方式不同。
foo.call(this, arg1,arg2,arg3) foo.apply(this, arguments) this.foo(arg1, arg2, arg3);案例1:
function Person(name, age) {this.name namethis.age age
}Person.prototype.eat function () {console.log(this.name 正在吃东西)
}p new Person(yuan, 22)p.eat()案例2:
function Person(name, age) {this.name namethis.age age
}
p new Person(yuan, 22)function eat () {console.log(this.name 正在吃东西)
}
eat.call(p)案例3:
function Person(name, age) {this.name namethis.age age
}
p new Person(yuan, 22)function eat () {console.log(this.name 正在吃东西)
}
eat.call(p)
eat.apply(p)如果call和apply的第一个参数写的是null那么this指向的是window对象 案例4:
function Person(name, age) {this.name namethis.age age
}p new Person(yuan, 22)function eat(a, b, c) {console.log(this.name 正在吃东西)console.log(a, b, c)
}eat.call(p, 1, 2, 3)
eat.apply(p, [1, 2, 3])
// apply传递多个参数的时候第二个参数需要传递一个数组【3】 eval函数
eval() 函数计算 JavaScript 字符串并把它作为脚本代码来执行。
如果参数是一个表达式eval() 函数将执行表达式。如果参数是Javascript语句eval()将执行 Javascript 语句。
eval(string)
//
eval([1,2,3,4,5].map(xx*x))http://tools.jb51.net/password/evalencode 【4】Hook函数
在 JS 逆向中我们通常把替换原函数的过程都称为 Hook。
function foo() {console.log(foo功能...)return 123
}
foo()var _foo foofoo function () {console.log(截断开始...)debugger;_foo()console.log(截断结束...)
}function foo(a, b, c, d, e, f) {console.log(foo功能...)console.log(a, b, c, d, e, f)return 123
}var _foo foofoo function () {console.log(截断开始...)// _foo(arguments)_foo.apply(this,arguments)console.log(截断结束...)
}foo(1,2,3,4,5,6,7)案例1: Hook eval
console.log(程序开始)
// eval(console.log(yuan))
window[eval](console.log(eval yuan))
console.log(程序结束)var _eval evaleval function (src) {console.log(eval截断开始...)debugger;_eval.apply(this, src)console.log(eval截断结束...)
}案例2: Hook JSON.stringify
JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串在某些站点的加密过程中可能会遇到以下代码演示了遇到 JSON.stringify() 时则插入断点
(function() {var stringify JSON.stringify;JSON.stringify function(params) {console.log(Hook JSON.stringif:::, params);debugger;return stringify(params);}
})();案例3: Hook JSON.parse
JSON.parse() 方法用于将一个 JSON 字符串转换为对象在某些站点的加密过程中可能会遇到以下代码演示了遇到 JSON.parse() 时则插入断点
(function() {var parse JSON.parse;JSON.parse function(params) {console.log(Hook JSON.parse::: , params);debugger;return parse(params);}
})();案例4: Hook Cookie
一般使用Object.defineProperty()来进行属性操作的hook。那么我们了解一下该方法的使用。
Object.defineProperty(obj, prop, descriptor)// 参数
obj对象
prop对象的属性名
descriptor属性描述符一般hook使用的是get和set方法下边简单演示一下
var people {name: 张三,
};Object.defineProperty(people, age, {get: function () {console.log(获取值);return count;},set: function (val) {console.log(设置值);count val 1;},
});people.age 18;
console.log(people.age);通过这样的方法我们就可以在设置某个值的时候添加一些代码比如 debugger;让其断下然后利用调用栈进行调试找到参数加密、或者参数生成的地方需要注意的是网站加载时首先要运行我们的 Hook 代码再运行网站自己的代码才能够成功断下这个过程我们可以称之为 Hook 代码的注入。
(function(){use strictvar _cookie ;Object.defineProperty(document, cookie, {set: function(val) {console.log(val);debugger_cookie val;return val;},get: function() {return _cookie;},
});
})()【5】Promise对象
Promise 是异步编程的一种解决方案比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现ES6 将其写进了语言标准统一了用法原生提供了Promise对象。Promise 是一个 ECMAScript 6 提供的类目的是更加优雅地书写复杂的异步任务。Promise是一个构造函数通过new来实例化主要解决异步编程。在 ES2015 中Promise 诞生了。Promise 成功解决了回调函数中嵌套调用和错误跟踪、回调函数控制权等问题。一个Promise对象有三种状态pending等待中、fulfilled已成功或rejected已失败。当Promise对象处于pending状态时它表示尚未完成但可能会在未来某个时间完成。
1回调函数
了解promise应该先懂回调简单理解回调函数能够实现异步编程(可以控制函数调用顺序)。紧接着你应该知道回调地狱或者函数瀑布就类似如下的代码
setTimeout(function () {console.log(apple);setTimeout(function () {console.log(banana);setTimeout(function () {console.log(cherry);}, 1000);}, 2000);
}, 3000);
console.log(下一个操作)Promise 的出现就能够将上面嵌套格式的代码变成了较为有顺序的从上到下风格的代码。
2基本语法 new Promise(function(resolve, reject) { });Promise构造函数接受一个函数作为参数该函数的两个参数分别是resolve和reject。它们是两个函数由 JavaScript 引擎提供不用自己部署。Promise 构造函数只有一个参数这个参数是一个函数这个函数在构造之后会直接被异步运行所以我们称之为起始函数。起始函数包含两个参数 resolve 和 reject。异步任务执行成功时调用resolve函数返回结果反之调用reject。Promise对象的then方法用来接收处理成功时响应的数据catch方法用来接收处理失败时相应的数据。
案例1 function sayHi() {var promise new Promise(function (resolve, reject) {// 模拟Ajax请求// var data hello world// console.log(请求完成,响应数据为, data)// resolve(data)setTimeout(function () {var data hello worldresolve(data)}, Math.random() * 5000)})return promise}sayHi().then(item console.log(item !!!)) // 异步操作不影响下面继续执行
console.log(下一个操作)3then函数
Promise实例生成以后可以用then方法分别指定resolved状态和rejected状态的回调函数**。** Promise实例具有then方法也就是说then方法是定义在原型对象Promise.prototype上的。它的作用是为 Promise 实例添加状态改变时的回调函数。前面说过then方法的第一个参数是resolved状态的回调函数第二个参数是rejected状态的回调函数它们都是可选的。 then方法返回的是一个新的Promise实例注意不是原来那个Promise实例。因此可以采用链式写法即then方法后面再调用另一个then方法。
.then(function (){}, function (){}); 如果初始函数里面没有指定resolve或者reject函数那么 .then 函数是不会被调用的因为之后状态变成了resolved或者rejected才会调用对应的回调函数。
const promise new Promise((resolve, reject) {console.log(apple);//resolve()
});
promise.then(() {console.log(banana);
});
console.log(cherry);
// 输出 apple cherry
// 这里没有输出banana因为promise实例的状态没有改变所以没有调用对应状态的回调函数
放开resolve()函数再试一下。结果先cherry后banana是因为 .then方法是微任务宏任务执行完毕后开始才开始执行微任务。
把上面的resolve函数换成reject()函数 const promise new Promise((resolve, reject) {console.log(apple);reject() });promise.then(() {console.log(banana);});console.log(cherry);因为.then方法并没有定义rejected状态相对应的回调函数。因为.then方法的第2个参数才是rejected状态的回调函数。所以改为
const promise new Promise((resolve, reject) {console.log(apple);reject()
});
promise.then(() {console.log(banana success);
},() {console.log(banana reject);
});
console.log(cherry);如果我们此时再在reject后面加上resolve输出结果和上面一样。这是因为状态只会改变一次之后不会更改的。如果把最开始的代码resolve放中间会怎样
const promise new Promise((resolve, reject) {console.log(apple);resolve(apple) // resolve仅仅设置了状态console.log(APPLE);
});
promise.then((res) {console.log(res banana);
}, () {console.log(banana);
});
console.log(cherry);promise执行流程
1. 构造函数中的输出执行是同步的输出 apple,执行 resolve 函数将 Promise 对象状态置为resolved输出APPLE。
2. 注册这个Promise对象的回调then函数。
3. 宏任务继续打印cherry,整个脚本执行完stack 清空。
4. eventloop 检查到 stack为空再检查 microtask队列中是否有任务发现了 Promise 对象的 then 回调函数产生的 microtask推入stack执行。输出apple bananaeventloop的列队为空stack为空脚本执行完毕。4链式应用
使用Promise可以更好地处理异步操作例如网络请求文件读取等。它避免了回调地狱callback hell的问题使得代码更加容易理解和维护。 // 第一层获取用户信息
function getUserInfo(userId) {return new Promise((resolve, reject) {// 模拟异步操作获取用户信息setTimeout(() {const userInfo {id: userId,name: John Doe,email: johndoeexample.com};resolve(userInfo);}, 1000);});
}// 第二层获取用户订单列表
function getUserOrders(userId) {return new Promise((resolve, reject) {// 模拟异步操作获取用户订单列表setTimeout(() {const orders [{id: 1, product: Product A},{id: 2, product: Product B},{id: 3, product: Product C}];resolve(orders);}, 2000);});
}// 第三层获取订单详情
function getOrderDetails(orderId) {return new Promise((resolve, reject) {// 模拟异步操作获取订单详情setTimeout(() {const orderDetails {id: orderId,status: Delivered,address: 123 Main St};resolve(orderDetails);}, 1500);});
}// 应用示例
const userId 123;getUserInfo(userId).then(userInfo {console.log(User Info:, userInfo);return getUserOrders(userInfo.id);}).then(orders {console.log(User Orders:, orders);const orderId orders[0].id;return getOrderDetails(orderId);}).then(orderDetails {console.log(Order Details:, orderDetails);}).catch(error {console.error(Error:, error);});console.log(后续操作)
5Promise与Ajax请求
原生Ajax function fetchData(url) {return new Promise(function (resolve, reject) {var xhr new XMLHttpRequest();xhr.open(GET, url);xhr.onload function () {if (xhr.status 200) {resolve(xhr.responseText);} else {reject(Error(xhr.statusText));}};xhr.onerror function () {reject(Error(Network Error));};xhr.send();});
}// 调用fetchData()函数并处理Promise对象的结果
fetchData(https://v0.yiketianqi.com/api?unescape1versionv9appid47284135appsecretjlmX3A6s).then(function (response) {// 如果Promise对象成功解决执行这里的代码var data JSON.parse(response)console.log(data:::, data)}).catch(function (error) {// 如果Promise对象被拒绝执行这里的代码console.log(Error loading data:, error);
});
jQuery版本
function fetchData(url) {return new Promise(function (resolve, reject) {$.ajax({url: url,success: function (res) {console.log(res:, res)resolve(res)}})});
}// 调用fetchData()函数并处理Promise对象的结果
urlhttps://v0.yiketianqi.com/api?unescape1versionv9appid47284135appsecretjlmX3A6s
fetchData(url).then(function (response) {// 如果Promise对象成功解决执行这里的代码const container $(#container);const html response.data.map(item divspan${item.day}/spanspan${item.wea}/span/div).join();container.append(html);
})