第6章 day06 2.Javascript高级

上节课遗留: JS中的函数(重点)

​ 函数在程序中代表的就是一段具有功能性的代码,可以让我们的程序编程更加具有结构性和提升程序的复用性,也能让代码变得更加灵活强大

声明函数

function 函数名 (参数){
    函数体;
    return 返回值;
}
功能说明:

    函数由关键字function定义
    函数名的定义规则与标识符一致,大小写是敏感的
    返回值必须使用return
    

函数调用

    //f(); --->OK
    function f(){
        console.log("hello")

    }
    f() //----->OK

函数参数

(1) 参数基本使用

// 位置参数
function add(a,b){

    console.log(a);
    console.log(b);
}
add(1,2)
add(1,2,3)
add(1)


// 默认参数
function stu_info(name,gender="male"){
    console.log("姓名:"+name+" 性别:"+gender)
}

stu_info("bobo")

函数返回值

在函数体内,使用 return 语句可以设置函数的返回值。一旦执行 return 语句,将停止函数的运行,并运算和返回 return 后面的表达式的值。如果函数不包含 return 语句,则执行完函数体内每条语句后,返回 undefined 值。

function add(x,y) {
          return x,y  //只会返回一个值x
      }

var ret = add(2,5);
console.log(ret)

1、在函数体内可以包含多条 return 语句,但是仅能执行一条 return 语句

2、函数的参数没有限制,但是返回值只能是一个;如果要输出多个值,可以通过数组或对象进行设计。

函数作用域

作用域是JavaScript最重要的概念之一。

JavaScript中,变量的作用域有全局作用域和局部作用域两种。

// 局部变量,是在函数内部声明,它的生命周期在当前函数被调用的时候, 当函数调用完毕以后,则内存中自动销毁当前变量
// 全局变量,是在函数外部声明,它的生命周期在当前文件中被声明以后就保存在内存中,直到当前文件执行完毕以后,才会被内存销毁掉

作用域案例:

var num = 10; // 在函数外部声明的变量, 全局变量
function func(){
  //千万不要再函数内部存在和全局变量同名的变量
  num = 20; // 函数内部直接使用变量,则默认调用了全局的变量,
}
func();
console.log("全局num:",num);

匿名函数

匿名函数,即没有变量名的函数。在实际开发中使用的频率非常高!也是学好JS的重点。

      // 匿名函数赋值变量
       var foo = function () {
           console.log("这是一个匿名函数!")
       };
      foo() //调用匿名函数
			

      // 匿名函数的自执行
      (function (x,y) {
           console.log(x+y);
       })(2,3)


     // 匿名函数作为一个高阶函数使用
     function bar() {

        return function () {
            console.log("inner函数!")
        }
    }
    bar()()
        

Javascript进阶

一. 变量提升(不正常现象)

看以下代码, 或多或少会有些问题的.

function fn(){
    console.log(name);
    var name = '大马猴';
}
fn()

发现问题了么. 这么写代码, 在其他语言里. 绝对是不允许的. 但是在js里. 不但允许, 还能执行. 为什么呢? 因为在js执行的时候. 它会首先检测你的代码. 发现在代码中会有name使用. OK. 运行时就会变成这样的逻辑:

function fn(){
    var name;
    console.log(name);
    name = '大马猴';
}
fn()

看到了么. 实际运行的时候和我们写代码的顺序可能会不一样....这种把变量提前到代码块第一部分运行的逻辑被称为变量提升. 这在其他语言里是绝对没有的. 并且也不是什么好事情. 正常的逻辑不应该是这样的. 那么怎么办? 在新的ES6中. 就明确了, 这样使用变量是不完善的. es6提出. 用let来声明变量. 就不会出现该问题了.

function fn(){
    console.log(name);  // 直接报错, let变量不可以变量提升.
    let name = '大马猴'; 
}
fn()

== 结论一, 用let声明变量是新版本javascript提倡的一种声明变量的方案.==

let还有哪些作用呢?

function fn(){
    var name = "周杰伦";
    var name = "王力宏";
    console.log(name);
}
fn()

显然一个变量被声明了两次. 这样也是不合理的. var本意是声明变量. 同一个东西. 被声明两次. 所以ES6规定. let声明的变量. 在同一个作用域内. 只能声明一次.

function fn(){
    let name = "周杰伦";
    console.log(name);
    let name = "王力宏";
    console.log(name);
}
fn()

注意, 报错是发生在代码检查阶段. 所以. 上述代码根本就执行不了.

结论二, 在同一个作用域内. let声明的变量只能声明一次. 其他使用上和var没有差别

注意:直接进行变量声明,不使用let和var的含义是什么?

不使用`var`直接赋值的变量,如果没有提前声明,它会成为全局变量。这意味着它可以在整个程序的任何地方访问和修改,这可能导致意外的副作用和难以调试的错误。

function fn(){
    name = '大马猴';
}
fn()
console.log(name)  //正确


function fn(){
    var name = '大马猴';
}
fn()
console.log(name)//报错


function fn(){
    var name = '大马猴';
}
fn()
console.log(name) //报错

二. 闭包函数

我们先看一段代码.

let name = "周杰伦";
function chi(){
    name = "吃掉";
}
chi();
console.log(name);

发现没有, 在函数内部想要修改外部的变量是十分容易的一件事. 尤其是全局变量. 这是非常危险的. 试想, 我写了一个函数. 要用到name, 结果被别人写的某个函数给修改掉了. 多难受.

接下来. 我们来看一个案例:

同时运行下面两组代码:

// 1号工具人.
var name = "alex"

setTimeout(function(){
    console.log("一号工具人:"+name) // 一号工具人还以为是alex呢, 但是该变量是不安全的.
}, 5000);

// 2号工具人
var name = "周杰伦"
console.log("二号工具人", name);

两组代码是在同一个空间内执行的. 他们拥有相同的作用域. 此时的变量势必是非常非常不安全的. 那么如何来解决呢? 注意, 在js里. 变量是有作用域的. 也就是说一个变量的声明和使用是有范围的. 不是无限的. 这一点, 很容易验证.

function fn(){
    let love = "爱呀"
}
fn()
console.log(love)

直接就报错了. 也就是说. 在js里是有全局和局部的概念的.

直接声明在最外层的变量就是全局变量. 所有函数, 所有代码块都可以共享的. 但是反过来就不是了. 在函数内和代码块内声明的变量. 它是一个局部变量. 外界是无法进行访问的. 我们就可以利用这一点来给每个工具人创建一个局部空间. 就像这样:

// 1号工具人.
(function(){
    var name = "alex";
    setTimeout(function(){
        console.log("一号工具人:"+name) // 一号工具人还以为是alex呢, 但是该变量是不安全的.
    }, 5000);
})();

// 二号工具人
(function(){
    var name = "周杰伦"
    console.log("二号工具人", name);
})();

这样虽然解决了变量的冲突问题. 但是...我们想想. 如果在函数外面需要函数内部的一些东西来帮我进行相关操作怎么办...比如, 一号工具人要提供一个功能(加密). 外界要调用. 怎么办?

// 1号工具人.
let encrypt_tool = (function(){
    let log_msg = '开始加密......\n'
    // 我是一个加密函数
    let encrypt = function(data){  // 数据
        console.log(log_msg) //打印日志信息(访问外部变量)
        // 返回密文
        return atob(data);//用于将一个Base64编码的字符串解码为原始的二进制数据
    }
    // 外面需要用到这个功能啊. 你得把这个东东返回啊. 返回加密函数
    return encrypt;
})();

//外部调用
console.log(encrypt_tool('i love you'));

注意了. 我们如果封装一个加密js包的时候. 好像还得准备出解密的功能. 并且, 不可能一个js包就一个功能吧. 那怎么办? 我们可以返回一个对象. 对象里面可以存放好多个功能. 而一些不希望外界触碰的功能. 就可以很好的保护起来.

// 1号工具人.
let encrypt_tool = (function(){
    let log_msg_1 = '开始加密......'
    let log_msg_2 = '开始解密......'

    // 我是一个加密函数
    let encrypt = function(data){  // 被加密数据
        console.log(log_msg_1) //打印日志信息(访问外部变量)
        // 返回密文
        return atob(data);
    };
    //解密函数
    let decrypt = function(en_data){  // 加密后的数据
        console.log(log_msg_2) //打印日志信息(访问外部变量)
        // 返回解密后的原数据
        return btoa(en_data);
    };
    // 外面需要用到这个功能啊. 你得把这个东东返回啊. 返回加密函数
    return {'encrypt':encrypt,'decrypt':decrypt};
})();

//外部调用
en_data = encrypt_tool.encrypt('i love you');
de_data = encrypt_tool.decrypt(en_data)
console.log(en_data);
console.log(de_data);

OK. 至此. 何为闭包? 上面这个就是闭包. 相信你百度一下就会知道. 什么内层函数使用外层函数变量. 什么让一个变量常驻内存.等等. 其实你细看. 它之所以称之为闭包~. 它是一个封闭的环境. 在内部. 自己和自己玩儿. 避免了对该模块内部的冲击和改动. 避免的变量之间的冲突问题.

闭包的特点:

  1. 内层函数对外层函数变量的使用.
  2. 会让变量常驻与内存.

三. JS中的各种操作(非交互)

3.1 定时器

在JS中, 有两种设置定时器的方案

// 语法规则
setTimeout(函数, 时间)
// 经过xxx时间后, 执行xxx函数

// 示例:3秒后打印我爱你
setTimeout(function(){
    console.log("我爱你")
}, 3000);

3.2 eval函数(必须会. 隔壁村老太太都会.)

eval本身在js里面正常情况下使用的并不多. 但是很多网站会利用eval的特性来完成反爬操作. 我们来看看eval是个什么鬼?

从功能上讲, eval非常简单. 它和python里面的eval是一样的. 它可以动态的把字符串当成js代码进行运行.

s = "console.log('我爱你')";
eval(s);

也就是说. eval里面传递的应该是即将要执行的代码(字符串). 那么在页面中如果看到了eval加密该如何是好? 其实只要记住了一个事儿. 它里面不论多复杂. 一定是个字符串.

比如,

eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('0.1(\'我爱你\')',62,2,'console|log'.split('|'),0,{}))

这一坨看起来, 肯定很不爽. 怎么变成我们看着很舒服的样子呢? 记住. eval()里面是字符串. 记住~!!

那我想看看这个字符串长什么样? 就把eval()里面的东西拷贝出来. 执行一下. 最终一定会得到一个字符串. 要不然eval()执行不了的. 对不...于是就有了下面的操作.

image-20210828160541107

http://tools.jb51.net/password/evalencode, 在赠送你一个在线JS处理eval的网站. 大多数的eval加密. 都可以搞定了.

3.3 prototype和_proto_(重点)

逆向代码示例:

function ct(t) {
    pv['$_BCAO'] = t || [];
}

ct.prototype = {
    '$_CAE':function(f) {
               f();
            }
} 

var H = new ct(t)['$_CAE'](function(t) {
        var e = function(t) {
            for (var e = [[1, 0], [2, 0], [1, -1], [1, 1], [0, 1], [0, -1], [3, 0], [2, -1], [2, 1]], r = e['length'],n = 0; n < r; n++){
                var b = 'stuvwxyz~';
            }   
            return b;
        };
    	return e;
    })


  • 原型

    • 概念:原型本身其实是一个function函数,可以将其理解成Python中的class类。

    • 创建一个原型:

      function User(name,pwd){
          this.userName = name;
          this.pwd = pwd;
          this.regist = function(){
              console.log(this.userName+"在注册")
          }
      }
      
  • 实例对象

    • 概念:通过new关键字创建的对象称为实例对象。

    • 创建实例对象:

      let u1 = new User('jay','123');
      let u2 = new User('tom','456');
      
  • 原型对象

    • 概念:原型对象用于存储所有实例对象共享的属性和方法,以减少每个实例对象重复存储相同属性和方法的开销。

    • 原型对象存储所有实例对象共享的属性和方法

      //类似于类属性
      User.prototype.address = "BJ";
      User.prototype.gender = "male";
      //类似于类方法
      User.prototype.login = function login(username, password){
          console.log(`${username}在登录`);
      }
      
      //实例对象共享原型对象存储的内容
      u1.login('jay','123');
      u2.login('tom','456');
      console.log(u1.address,u2.address,u1.gender,u2.gender);
      
    • 获取原型对象:

      User.prototype;   //类似于访问所有的类成员
      u1.__proto__;
      User.prototype === u1.__proto__ //true
      //可以通过原型名访问原型对象或者使用实例名访问原型对象
      
  • 原型链

    • 原型链是JavaScript中对象继承属性和方法的一种方式。具体介绍如下:

      原型链是JavaScript中对象继承属性和方法的一种方式。当访问一个对象的属性或方法时,如果该对象本身没有这个属性或方法,它会通过原型链去它的原型对象中查找,如果原型对象也没有,会继续在其原型的原型中查找,这样逐级向上,直到找到属性或方法或者达到原型链的末端。
      

      原型对象本身也是一个对象,它也可以使用__proto__访问它的原型对象,类似于:

      u1.__proto__.__proto__
      
    • 原型链的成员访问:

      • 实例对象可以访问其原型内的成员和其原型链上所有原型对象内的成员
      u1.toString()
      
  • 浏览器环境navigator分析

    Snipaste_2024-07-11_09-24-19

练习测试:理解下属代码

function ct(t) {
    pv['$_BCAO'] = t || [];
}

//[]表示.调用对象成员
var H = new ct(t)['$_CAE'](function(t) {
        var e = function(t) {
            for (var e = [[1, 0], [2, 0], [1, -1], [1, 1], [0, 1], [0, -1], [3, 0], [2, -1], [2, 1]], r = e['length'],n = 0; n < r; n++){
                var b = 'stuvwxyz~';
            }   
            return b;
        };
    	return e;
    })

ct.prototype = {
    '$_CAE':function(f) {
               f();
            }
}

3.4 神奇的window(浏览器环境,在console中执行代码)

window对象是一个很神奇的东西. 你可以把这东西理解成javascript的全局. 如果我们默认不用任何东西访问一个标识符. 那么默认认为是在用window对象进行访问该标识符.

例如:

var a = 10; 
a === window.a  // true

window.mm = "爱你"
console.log(mm); //"爱你"

综上, 我们可以得出一个结论. 全局变量可以用window.xxx来表示.

注意:window对象实际上表示的是浏览器的窗口。浏览器的窗口只有浏览器有。我们在浏览器中的开发者工具的Console选项卡中是可以直接使用window对象。

但是:在pycharm中直接使用window对象会报错:ReferenceError: window is not defined。why?就是因为在pycharm中是没有浏览器窗口。

所以切记:window对象是专属于浏览器环境下的一个内置对象。就意味着window只可以在浏览器环境下无需声明直接被使用。

ok. 接下来. 注意看了. 我要搞事情了

//如果想在外部调用下面函数的中的chi函数如何实现?
(function(){
    let chi = function(){
        console.log("我是吃")
    }
})();
chi() //会报错,因为chi是一个局部变量

//正确写法:
(function(){
    let chi = function(){
        console.log("我是吃")
    }
    window.chi = chi //全局的
})();
chi();

//换一种写法. 你还认识么?
(function(w){
    let chi = function(){
        console.log("我是吃")
    }
    w.chi = chi
})(window);

如何在node环境下执行上述代码?

globalThis在浏览器和node中都可以使用。在Pycharm中就可以使用globalThis代替window用于全局变量的声明

//全局变量的声明
globalThis.a = 10;
console.log(a);

window是整个浏览器的全局作用域.

使用 window 对象也可以访问客户端其他对象,这种关系构成浏览器对象模型,window 对象代表根节点,浏览器对象关系的关系如图所示,每个对象说明如下。

  • window:客户端 JavaScript 顶层对象。每当 或 标签出现时,window 对象就会被自动创建。
  • navigator:包含客户端有关浏览器信息。
  • screen:包含客户端屏幕的信息。
  • history:包含浏览器窗口访问过的 URL 信息。
  • location:包含当前网页文档的 URL 信息。
  • document:包含整个 HTML 文档,可被用来访问文档内容及其所有页面元素。
image-20240528194905528-6896946

3.5 call和apply

对于咱们逆向工程师而言. 并不需要深入的理解call和apply的本质作用. 只需要知道这玩意执行起来的逻辑顺序是什么即可(外部函数关联对象的内部成员)

在运行时. 正常的js调用:

function People(name, age){
    this.name = name;
    this.age = age;
    this.chi = function(){
        console.log(this.name, "在吃东西")
    }
}
var p1 = new People("alex", 18);
var p2 = new People("wusir", 20);
p1.chi();
p2.chi();

接下来, 我们可以使用call和apply也完成同样的函数调用

function People(name, age){
    this.name = name;
    this.age = age;
    this.chi = function(){
        console.log(this.name, "在吃东西")
    }
}
p1 = new People("alex", 18);
p2 = new People("wusir", 20);
p1.chi();
p2.chi();

//外部函数关联对象的内部函数:
	//想要让alx吃:"馒头", "大饼",如何调用下面的函数?
function eat(what_1, what_2){
    console.log(this.name, "在吃", what_1, what_2);
}
// call的语法是: 函数.call(对象, 参数1, 参数2, 参数3....)
// 执行逻辑是: 执行函数. 并把对象传递给函数中的this.  其他参数照常传递给函数
eat.call(p1, "馒头", "大饼");

apply和他几乎一模一样. 区别是: apply传递参数要求是一个数组

eat.apply(p1, ["馒头", "大饼"]);

3.6 ES6中的箭头函数

在ES6中简化了函数的声明语法.

var fn = function(){};
// 如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。
var fn = () => {};

var fn = function(name){}
var fn = name => {}
var fn = (name) => {}

var fn = function(name, age){}
var fn = (name, age) => {}

var f = v => v*v
// 等同于
var f = function(v) {
 return v*v
}

3.7 exports

类似Python中的模块导入

// functions.js文件

// 加法函数
function add(a, b) {
  return a + b;
}

// 乘法函数
function multiply(a, b) {
  return a * b;
}

// 导出函数
exports.add = add;
exports.multiply = multiply;
// main.js

// 导入 functions 模块
const functions = require('./functions');

// 使用导入的函数
console.log(functions.add(2, 3));  // 输出: 5
console.log(functions.multiply(4, 5));  // 输出: 20

四. DOM对象(了解)

DOM document Object Model 文档对象模型

// 整个html文档,会保存一个文档对象document
// console.log( document ); // 获取当前文档的对象

查找标签

  • 直接查找标签
document.getElementsByTagName("标签名")
document.getElementById("id值")
document.getElementsByClassName("类名")
//返回dom对象,就是标签对象或者数组
  • CSS选择器查找
document.querySelector("css选择器")  //根据css选择符来获取查找到的第一个元素,返回标签对象(dom对象)
document.querySelectorAll("css选择器"); // 根据css选择符来获取查找到的所有元素,返回数组
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>


<div id="i1">DIV1</div>

<div class="c1">DIV</div>
<div class="c1">DIV</div>
<div class="c1">DIV</div>


<div class="outer">
    <div class="c1">item</div>
</div>


<div class="c2">
    <div class="c3">
        <ul class="c4">
            <li class="c5" id="i2">111</li>
            <li>222</li>
            <li>333</li>
        </ul>
    </div>
</div>

<script>

   // 直接查找
   var ele = document.getElementById("i1");  // ele就是一个dom对象
   ele.innerText = 'hello bobo'; //将该标签内容修改成了hello bobo
   console.log(ele);

   var eles = document.getElementsByClassName("c1"); // eles是一个数组 [dom1,dom2,...]
   console.log(eles);

   var eles2 = document.getElementsByTagName("div"); // eles2是一个数组 [dom1,dom2,...]
   console.log(eles2);

  //定位outer下的c1对应的标签
   var outer = document.getElementsByClassName("outer")[0];
   var te = outer.getElementsByClassName("c1");
   console.log(te);

    // css选择器
		//层级定位(空格可以表示一个或多个层级)
    var dom = document.querySelector(".c2 .c3 .c5");
    console.log(":::",dom);
		//层级定位
    var doms = document.querySelectorAll("ul li");
    console.log(":::",doms);
    
</script>

</body>
</html>

绑定事件

  • 静态绑定 :直接把事件写在标签元素中
<div id="div" onclick="foo()">click</div>

<script>
    function foo(){           
        console.log("foo函数");   
    }
</script>

  • 动态绑定:在js中通过代码获取元素对象,然后给这个对象进行后续绑定
<p id="i1">试一试!</p>

<script>

    var ele=document.getElementById("i1");

    ele.onclick=function(){
        console.log("ok");
        
    };

</script>

五. jQuery和Ajax(了解)

jQuery是一个曾经火遍大江南北的一个Javascript的第三方库. jQuery的理念: write less do more. 其含义就是让前端程序员从繁琐的js代码中解脱出来. 我们来看看是否真的能解脱出来.

python => 基础语法 => 系统模块 => 第三方的库

jQuery的下载:

​ jquery:

https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/1.9.1/jquery.js

https://code.jquery.com/jquery-3.6.0.min.js

只需要把上面这个jquery下载的网址复制到浏览器上, 然后保存(ctrl+s)成js文件就可以了.

一. jQuery初使用

导入jQuery

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

我们用jQuery来完成一个按钮的基本点击效果. 当然, 得和传统的js对比一下

先准备好html. 页面结构. 这里复制粘贴就好

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
    <div class="div-out">
        <input type="button" class="btn" value="我是按钮. 你怕不怕">
        <div class="mydiv">我怕死了...</div>
    </div>
</body>
</html>

需求: 点击按钮. 更改mydiv中的内容.

// 传统js
window.onload = function(){
    document.querySelector(".btn").onclick = function(){
        document.querySelector('.mydiv').innerText = "我好啪啪啊";
    };
}
// jQuery
$(function(){  // $(document).ready(function(){
    $(".btn").click(function(){
        $(".mydiv").text('我要上天');
    })
})

除了$外, 其他东西貌似都挺容易理解的. 而且代码简洁. 异常舒爽.

$是什么鬼, 在jQuery中, $可以认为是jQuery最明显的一个标志了. $()可以把一个普通的js对象转化成jQuery对象. 并且在jquery中 $的含义就是jQuery.

二. jQuery选择器

jQuery的逻辑和css选择器的逻辑是一样的.

// 语法:
$(选择器)

可以使用jQuery选择器快速的对页面结构进行操作.

案例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
	<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>

        $(function(){
            $(".btn").on('click', function(){
                $(".info").text("");
                let username = $("#username").val();
                let password = $("#password").val();
                let gender = $("input:radio[name='gender']:checked").val();  // input标签中radio 并且name是gender的. 并且被选择的.
                let city = $("#city").val();

                let flag = true;
                if(!username){
                    $("#username_info").text('用户名不能为空!');
                    flag = false;
                }

                if(!password){
                    $("#password_info").text('密码不能为空!');
                    flag = false;
                }

                if(!gender){
                    $("#gender_info").text('请选择性别!');
                    flag = false;
                }

                if(!city){
                    $("#city_info").text('请选择城市!');
                    flag = false;
                }

                if(flag){
                    $("#login_form").submit();
                } else {
                    return;
                }
            })
        })

    </script>
</head>
<body>
    <form id="login_form">
        <label for="username">用户名: </label><input type="text" id="username" name="username"><span class="info" id="username_info"></span><br/>
        <label for="password">密码: </label><input type="password" id="password" name="password"><span class="info" id="password_info"></span><br/>
        <label>性别: </label>
            <input type="radio" id="gender_men" name="gender" value="men"><label for="gender_men">男</label>
            <input type="radio" id="gender_women" name="gender" value="women"><label for="gender_women">女</label>
            <span class="info" id="gender_info"></span>
        <br/>

        <label for="city">城市: </label>
            <select id="city" name="city">
                <option value="">请选择</option>
                <option value="bj">北京</option>
                <option value="sh">上海</option>
                <option value="gz">广州</option>
                <option value="sz">深圳</option>
            </select>
            <span class="info" id="city_info"></span>
        <br/>

        <input type="button" class="btn" value="登录">
    </form>
</body>
</html>

三. 发送ajax请求

  • 什么是ajax?

    • AJAX = 异步的javascript和XML(Asynchronous Javascript and XML)

    • 它不是一门编程语言,而是利用JavaScript在保证页面不被刷新、页面链接不改变的情况下与服务器交换数据并更新部分网页的技术。

    • 对于传统的网页,如果想更新内容,那么必须要刷新整个页面,但有了Ajax,便可以在页面不被全部刷新的情况下更新其内容。在这个过程中,页面实际上是在后台与服务器进行了数据交互,获得数据之后,再利用JavaScript改变页面,这样页面内容就会更新了。

    • 简言之,在不重载整个网页的情况下,AJAX通过后台加载数据,并在网页上进行显示。

    • 通过 jQuery AJAX 方法,您能够使用 HTTP Get 和 HTTP Post 从远程服务器上请求文本、HTML、XML 或 JSON - 同时您能够把这些外部数据直接载入网页的被选元素中。

    • //get()方式
        $.ajax({
           url:'./data/index.txt',
           type:'get',
            //当请求成功后,执行下面的匿名函数,函数参数data就是请求到的数据
           success:function(data){
              $('p').html(data);
      
           },
           error:function(error){
              console.log(error)
           }})
      
    • //post()方式
      $.ajax({
         url:'/index',
         type:'post',
         data:{name:'张三',age:12},//post的请求参数
         success:function(dd){
            $('p').html(dd);
         },
         error:function(error){
            console.log(error)
      }
      
    • // 创建一个新的XMLHttpRequest对象
      let xhr = new XMLHttpRequest();
      
      // 设置请求方法和URL
      xhr.open('GET', 'https://xxx.com', true);
      
      // 设置请求完成时的回调函数
      xhr.onload = function() {
        if (xhr.status >= 200 && xhr.status < 400) {
          // 请求成功,处理返回的数据
          let data = JSON.parse(xhr.responseText);
          console.log(data);
        } else {
          // 请求失败,处理错误
          console.error('请求失败,状态码:' + xhr.status);
        }
      };
      
      // 设置请求过程中发生错误的回调函数
      xhr.onerror = function() {
        console.error('请求过程中发生错误');
      };
      
      // 发送请求
      xhr.send();
      
      
posted @ 2025-09-29 17:09  凫弥  阅读(32)  评论(0)    收藏  举报