JS基础知识

1.延迟加载JS

在script标签上添加async或者defer

<script defer type="text/javascript" src="script.js"></script>

defer:等html全都解析完成,顺次执行js脚本

async:js谁先加载完谁先运行

 

2.JS数据类型有哪些?

基本数据类型:String,Number,Boolean,undefined,null,Symbol,BigInt

引用数据类:Object

typeof 1 // 'number'

typeof '1' // 'string'

typeof undefined // 'undefined'

typeof true // 'boolean'

typeof Symbol() // 'symbol'

typeof [] // 'object'

typeof {} // 'object'

typeof console.log // 'function'

因此采用typeof判断对象数据类型是不合适的,采用instanceof会更好,instanceof的原理是基于原型

链的查询,只要处于原型链中,判断永远为true

var str1 = 'hello world'

str1 instanceof String // false

 

字符串与别的相加都是字符串相连

undefined +1 --NAN 数值类型,但不是具体数字

3.null与undefined的区别

现有null,但是null转化为0,不容易发现错误。所以设计undefined

null 转为数值是 0 ; undefined 转为数值是 NAN(not a number)

null 通过 typeof 判断类型的时候结果的输出是 object ; 而 undefined 的类型是 undefined

4.==与===不同

null == undefined => true

string == number =>(隐式转换:string->number) true

boolean == number =>(boolean ->number) true

object == string|| number => (object 转换为基本类型)

隐式转换利用valueOf不会被体现出来

5.JS的微任务和宏任务

JS是单线程的语言,同一时间只能做一件事

执行流程:同步 =》事件循环【微任务、宏任务】

进入事件循环:请求、定时器、事件

for (var i = 0; i < 3; i++) {
    setTimeout(function () {
        console.log(i)
    }, 1000 * i)
}

 

微任务:promise.then是微任务,promise是同步

宏任务:setTimeout

宏任务执行前先执行所有微任务

6.JS作用域ß

1)除了函数外,js没有块级作用域

2)作用域内可以访问外部变量,但是外部不能访问内部,如果内部有优先就近,没有向外查找

3)声明变量是用var还是没有写(window.)

4) js有变量提升的机制(变量悬挂)var声明不赋值,不报错,提前打印值为undefined

5) 优先级:声明变量 > 普通函数 > 参数 >变量提升

先查找本层有没有变量(包括变量提升)

js除了函数没有块级作用域,

普通声明函数是不看写函数顺序的

function c() {
    var b = 1;
    function a() {
        console.log(b);
        var b = 2;
        console.log(b);
    }
    a();
    console.log(b);
}
c() // undefined 2 1
// 《《《《《《《《《《
var name = "world";
(function () {
    if (typeof name === 'undefined') {
        var name = 'JACK';
        console.log('GOODBYE' + name)
    } else {
        console.log('Hello ' + name)
    }
})()
// GOODBYEJACK
// 《《《《《《《《《《
var bar = 1;
function test() {
    console.log(bar);
    var bar = 2;
    console.log(bar)
}
test() // undefined 2;

7.JS对象

console.log([1, 2, 3] === [1, 2, 3]); //false

1.对象是通过new操作符构建出来,所以对象之间不相等(除了引用外)

2.对象注意:引用类型

3.对象的key都是字符串类型

4.对象查找属性

先在对象本身找 ==》构造函数找 ==》对象原型中找 ==》构造函数原型中找 ==》对象上一层原型上找

var obj1 = {
    a: 'hello'
}
var obj2 = obj1
obj2.a = 'world'
console.log(obj1) // {a:world}
    (function () {
        console.log(a) // undefined
        var a = 1;
    })()
// 《《《《《《《《《《
var a = {};
var b = {
    key: 'a'
}
var c = {
    key: 'c'
}
a[b] = '123'; // a = {'[object,object]':'123'};
a[c] = '456'; // a = {'[object,object]':'456'};
console.log(a[b]); // '456' 

 

1.每一个函数自带一个原型

注意:对象拥有__proto__

2.new Fun 该构造函数的原型指向于对象(new Fun)的原型

function Fun() {
    this.a = '这是Fun函数中添加的'
}
Fun.prototype.a = '这是Fun函数原型添加的'
let obj = new Fun();
obj.a = '对象本身';
obj.__proto__.a = '这是对象原型添加的'

8.JS作用域 + this指向 + 原型

function Foo() {
    getName = function () {
        alert(1);
    }
    return this;
}
Foo.getName = function () {
    alert(2);
}
Foo.prototype.getName = function () {
    alert(3);
}
var getName = function () {
    alert(4);
}
function getName() {
    alert(5);
}
Foo.getName(); //2 
getName();    //4 
Foo().getName();//1 
getName(); //1 
new Foo().getName();//3
new Foo().getName;//f(){  alert(3); }
// 《《《《《《《《《《
// this指到离他最近的一个对象 ,全局是window
var o = {
    a: 10,
    b: {
        fn: function () {
            console.log(this.a);// undefined
            console.log(this); // fn(){}
        }
    }
}
o.b.fn();
// 《《《《《《《《《《
window.name = 'Byte';
function A() {
    this.name = 123;
}
A.prototype.getA = function () {
    console.log(this);
    return this.name + 1;
}
let a = new A;
let funcA = a.getA; //  this.name= 'Byte'
// let funcA = a.getA();//  this.name= '123'
funcA();
// 《《《《《《《《《《
var length = 10;
function fn() {
    return this.length + 1;
}
var obj = {
    length: 5,
    test1: function () {
        return fn();
    }
}
obj.test2 = fn;
console.log(obj.test1()); // 11
console.log(fn() === obj.test2());// false this变了
console.log(obj.test1() == obj.test2()); // false

9.JS变量是不是数组

var arr = [1, 2];
// console.log(typeof(arr)); // 不可以 object
console.log(Array.isArray(arr));
console.log(arr instanceof Array);
console.log(Object.prototype.toString.call(arr).indexOf('Array') > -1)
console.log(Array.prototype.isPrototypeOf(arr));
console.log(arr.constructor.toString().indexOf('Array') > -1)

10.slice是干什么的,splice是否改变原数组

slice截取,找到坐标,之后的值,不改变原数组

var arr1 = ['a', 'v', 'd'];
var arr2 = arr1.slice(-1);
console.log(arr2)

splice 插入、删除、替换,改变原数组

arr1.splice(1,2) 删除1个,从2开始,改变原数组

11.JS去重

var arr3 = [1, 2, 3, 1, 4, 5];
console.log(new Set(arr3));
console.log(Array.from(new Set(arr3)));
console.log([...new Set(arr3)]);
function unique(arr) {
    return [...new Set(arr)]
}
function unique2(arr) {
    var brr = [];
    arr.forEach(element => {
        if (brr.indexOf(element) == -1) {
            brr.push(element);
        }
    });
    return brr;
}
function unique3(arr) {
    arr = arr.sort();
    var brr = [[arr[0]]];
    arr.forEach((el, index) => {
        if (el !== arr[index - 1]) {
            brr.push(el);
        }
    })
    return brr;
}

12.找出多维数组最大值

// 大数组分为四个小数组,将每个小数组内最大的值串联出来,形成一个新的数组
function fnArr(arr) {
    var newArr = [];
    arr.forEach((item, index) => {
        newArr.push(Math.max(...item))
    })
    return newArr;
}

13.给字符串新增方法实现功能

String.prototype.addText = function (str) {
    return str + this;
}
console.log('sdfsfsdf'.addText('dsf'));

14.找出字符串出现最多次数的字符以及次数

var str = 'sdfsdfsasdfsgddd4tgrg';
var obj = {};
for (var i = 0; i < str.length; i++) {
    var char = str.charAt(i);
    if (obj[char]) {
        obj[char]++;
    } else {
        obj[char] = 1;
    }
}
console.log(obj);
var max = 0;
for (var key in obj) {
    if (max < obj[key]) {
        max = obj[key];
    }
}
for (var key in obj) {
    if (obj[key] == max) {
        console.log(key + ':' + max)
    }
}

15.new操作符具体做了什么

function create(fn, ...args) {
    // 1.创建一个空的对象
    var obj = {};
    // 2.将空对象的原型,指向于构造函数的原型
    Object.setPrototypeOf(obj, fn.prototype);
    // 3.将空对象作为构造函数的上下文(改变this指向)
    var result = fn.apply(obj, args);
    // 4.对构造函数有返回值的处理判断
    return result instanceof Object ? result : obj;
}

function hh() {
    console.log(this);
};
console.log(new hh());

16.闭包

a.闭包是什么

闭包是一个函数加上创建函数的作用域的连接,闭包“关闭”了函数的自由变量

b.闭包可以解决什么问题

内部函数可访问到外部变量的局部变量

闭包可以解决问题

var lis = document.getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
    (function (i) {
        lis[i].onclick = function () {
            alert(i)
        }
        lis[i] = null;
    })(i)
}

c.闭包的缺点

变量会驻留在内存中,早晨内存损耗问题

把闭包函数设为null

内存泄露是IE浏览器存在问题

17.原型链

a.原型可以解决什么问题

共享属性、共享方法

b.谁有原型

function.prototype === obj.__proto__

function Fun() {
    this.run = '1';
}
Fun.prototype.run = '2';
var obj = new Fun();
obj.run = '3';
obj.__proto__ = '4';
Object.prototype.run = '5';
console.log(obj.run)

c.对象查找属性或者方法的顺序

现在对象本身查找 -》构造函数查找 -》原型查找 -》构造函数的原型查找 -》当前原型的原型查找

d.原型链:把原型串联起来,最顶端null

17.JS继承方式

// 方式一:ES6
class Parent1 {
    constructor() {
        this.age = 18;
    }
}
class Child1 extends Parent1 {
    constructor() {
        super();
        this.name = '张三'
    }
}
let o1 = new Child1();
console.log(o1, o1.name, o1.age)
// 方式二:原型链继承
function Parent2() {
    this.age = 18;
}
function Child2() {
    this.name = '张三'
}
Child2.prototype = new Parent2();
let o2 = new Child2();
console.log(o2, o2.name, o2.age)
// 方式三:借用构造函数
function Parent3() {
    this.age = 18;
}
function Child3() {
    this.name = '张三'
    Parent3.call(this);
}
let o3 = new Child3;
console.log(o3, o3.name, o3.age)
// 方式四:组合式继承
function Parent4() {
    this.age = 100;
}
function Child4() {
    Parent4.call(this);
    this.name = '张三'
}
Child4.prototype = new Parent4();
let o4 = new Child4();
console.log(o4, o4.name, o4.age)

18.call apply bind的区别 

共同点:都可以改变this指向

var str = '你好';
var obj = {
    str:'这是obj对象内部的str'
}
function fun(name,age) {
    console.log(this , this.str);
}
// fun.call( obj ,'123sdddd',18); //call会立即执行
// fun.apply( obj,['123sdddd',18] )//apply会立即执行
// fun.bind( obj,'123sdddd',18 )()
fun.bind( obj ) // bind 不会立即执行 fun.bind( obj )()
fun();

区别:

1.call,apply可以立即执行,bind不会立即执行,因为bind的返回的是一个函数需要加入()执行

2.参数不同:apply 第二个参数是数组,call和bind有多个参数需要挨个写

场景:

// 1.用apply的情况
var arr1 =  [1,2,3,4,5,7,78,223]
console.log(Math.max.apply(null,arr1));
// 2.用bind的情况
btn.onclick = function () {
    console.log(this.id)
}.bind(hls)

19.sort原理

sort()方法用于对数组元素的排序并返回数组,默认排序顺序是根据字符串unicode

array.sort(sortby);参数sortby可选,规定顺序排序,必须是函数;

如果调用该方法时没有使用参数,将按照字母顺序对数组中元素进行排序,说的更精确点,是按照字符编码进行排序,要实现这一点,

console.log(arr1.sort());
console.log(arr1.sort(function (a,b) {
    return a - b;
}));
// 有对象的数组
function funSort(age) {
    return function(a,b){
        var val1 = a[age];
        var val2 = b[age];
        return val1 - val2;
    }
}
var arr5 = arr4.sort(funSort('age'));
console.log(arr5)
// v8引擎排序,之前数量小于10用插入排序,数量大于10,快速排序,现在是冒泡

20.深拷贝和浅拷贝

共同点:复制

浅拷贝:只复制引用,未复制真正的值(相互影响)

var objC1 = {a:1,b:2}

var objC2 = Object.assign(objC1);

console.log(objC1,objC2)

深拷贝:是复制真正的值(不同引用)

// 方法一:JSON.parse
var objC3 = {
    a:1,
    b:2
}
var objC4 = JSON.parse(JSON.stringify(obj3));
console.log(objC3,objC4);
// 方法二:递归的形式
function copyObj(obj) {
    if(Array.isArray(obj)){
        var newObj = [];
    }else{
        var newObj = {}
    }
    
    for(var key in obj){
        if(typeof obj[key]== 'object'){
            newObj[key] = copyObj(obj[key])
        }else{
            newObj[key] = obj[key]
        }
    }
    return newObj;
}

 21.localStorage sessionStorage cookie的区别

a.cookie数据始终携带在同源的http请求中,即cookie在浏览器和服务器间来回传递,而sessionStorage和Localstorage不会自动把数据发送给服务器,只在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。
b.存储大小限制也不同,cookie数据不能超过4k,同时因为每次http请求都会携带cookie,所有cookie只适合保存很小的数据。如会话标识。sessionStorage和Localstorage虽然也有大小储存的限制,但比cookie大很多。可以达到5M或更大
c.数据有效期不同,sessionStorage,仅在当前浏览器窗口关闭之前有效,Localstorage始终有效,窗口或者浏览器关闭也一直保存,除非手动删除,cookie只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭。
d.作用域不同,sessionStorage不能在不同的浏览器中共享,即使是同一个页面,locastorage在所有的同源窗口中都是共享的,cookie也是在所有同源窗口中共享的
e.web Storage支持事件通知机制,可以将数据更新的通知发送给监听者。
f.web storage 的api接口使用更方便。

22.var let const 的区别

a.var具有变量提升的机制,let和const没有变量提升的机制

b.var可以多次声明同一个变量,let和const不行

c.var let声明变量,const声明常量

var let可以改变值的大小 const不可以改,但是内层const没有声明可以更改

23.作用域

注意一:let const没有变量提升性

注意二:

function demo() {
    let n = 2;
    if( true ){
        let n =1;
    }
    console.log(n);//2
}
demo();

24.合并下列对象

const a = {a:1,b:4};
const b = {b:2,c:3};
// 方式一:
let objS1 = Object.assign(a,b);
console.log( objS1 );
// 方式二:s
let objS2 = { ...a,...b }
console.log( objS2 );
// 方式三:
function extend(target,source) {
    for(var obj in source){
        target[obj] = source[obj];
    }
    return target;
}
console.log( extend(a,b));

25.箭头函数和普通函数的区别

a.指向的问题

箭头函数中this只在箭头函数定义时就决定的,而且不可修改(call\apply\bind)

箭头函数的this指向定义的时候、外层第一个普通函数this

b.箭头函数不能new(不能当做构造函数)

c.箭头函数没有prototype

e.箭头函数没有arguments

let obj = {
    a:function () {
        console.log(this); //函数自身
    },
    b: () => {
        console.log(this);// window
    }
}

26.promise 有几种状态

a.promise:pending(进行中) fulfilled(已成功) reject(已失败)

b.generator函数

* getData(){
    yield http.$axios({url:'/home'});
    yield http.$axios({url:'/api'});
  
 }
 let t = this.getData();
// console.log(t.next().value);
t.next().value.then(res =>{
    console.log(res);
}) // home
t.next().value.then(res =>{
    console.log(res);
}) // api
// async await
async created(){
    let p = await http.$axios({url:'/home'});
}

27.find和filter 的区别

区别一:返回内容不一样

filter 返回是新数组

find 返回具体的内容

let arr = [123,12,23,44,3,53,43,45,6,4,5]

console.log(arr.filter(val=>{return val>10})) //[123, 12, 23, 44, 53, 43, 45]

console.log(arr.find(val=>{return val>10})) //123

区别二

filter 返回整个整体(每一个匹配到的都返回)

find 匹配到第一个即返回

28.some和every的区别

some 有一个匹配就返回true

every 全部匹配才会返回true

var arrA = [1,4,2,10,6];
var brr = arrA.some(val => {
    return val >4;
}) // true
var crr = arrA.every(val=>{
    return val>4;
}) // false

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/17428.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot访问静态资源

SpringBoot项目中没有WebApp目录&#xff0c;只有src目录。在src/main/resources下面有static和templates两个文件夹。SpringBoot默认在static目录中存放静态资源&#xff0c;而templates中放动态页面。 static目录 SpringBoot通过/resources/static目录访问静态资源&#xff…

完成A轮融资,倍思如何发力场景化为品牌创造广阔未来?

凛冬过后的消费电子正在重新凝聚资本的目光。 近日&#xff0c;深圳市倍思科技有限公司宣布完成由深创投、中金资本联合领投&#xff0c;越秀产业基金、高榕资本跟投&#xff0c;金额数亿元人民币的A轮融资。 分析人士指出&#xff0c;消费电子的行业景气度在逐渐恢复&#x…

中国社科院与美国杜兰大学金融管理硕士项目——迎接立夏,切莫忘记自我成长

五月的风吹走了春季&#xff0c;今天我们迎来立夏。作为夏季的第一个节气&#xff0c;立夏常被人们当做万物蓄满能量&#xff0c;即将加速生长的标志。而在职的我们&#xff0c;也应该跟这世间万物一样&#xff0c;在季节交替之时沉淀自己、努力向上成长。在社科院与杜兰大学金…

“人工智能教父”从谷歌离职 称后悔发展AI,为世人敲响警钟?

在加入谷歌的第十年、深度学习迎来爆发式发展的当下&#xff0c;被誉为“人工智能教父”的Geoffrey Hinton已从谷歌离职&#xff0c;只是为了告诫人们AI已经变得很危险。 公开资料显示&#xff0c;Geoffrey Hinton在2013年加入谷歌&#xff0c;曾任副总裁&#xff0c;研究机器学…

成为数据分析师,需要具备哪些技能?

随着互联网的发展&#xff0c;数据分析师的特点越来越明显&#xff0c;对数据分析师综合素质的要求也较高。 1、较强的数据挖掘、信息整理、和逻辑分析能力 数据分析&#xff0c;也是数据分析师的一个方向。 制作日常性的经营报表&#xff0c;对公司或者行业KPI指标进行拆解…

Mysql索引(3):索引分类

1 索引分类 在MySQL数据库&#xff0c;将索引的具体类型主要分为以下几类&#xff1a;主键索引、唯一索引、常规索引、全文索引。 分类含义特点关键字主键索引针对于表中主键创建的索引 默认自动创建, 只能有一个 PRIMARY 唯一索引 避免同一个表中某数据列中的值重复可以有多…

【Android入门到项目实战-- 8.4】—— 如何解析JSON格式数据

目录 一、准备工作 二、使用JSONObject 三、使用GSON 比起XML&#xff0c;JSON的主要优势在于它的体积更小&#xff0c;在网络上传输的时候可以更省流量&#xff0c;但缺点是语义性较差&#xff0c;看起来不直观。 一、准备工作 还是使用前面文章的方法&#xff0c;在服务器…

每日学术速递4.29

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.LG 1.A Cookbook of Self-Supervised Learning 标题&#xff1a;自监督学习食谱 作者&#xff1a;Randall Balestriero, Mark Ibrahim, Vlad Sobal, Ari Morcos, Shashank Shekhar, Tom…

【黑马程序员 C++教程从0到1入门编程】【笔记8】 泛型编程——模板

https://www.bilibili.com/video/BV1et411b73Z?p167 C泛型编程是一种编程范式&#xff0c;它的核心思想是编写通用的代码&#xff0c;使得代码可以适用于多种不同的数据类型。 而模板是C中实现泛型编程的一种机制&#xff0c;它允许我们编写通用的代码模板&#xff0c;然后在需…

【Spring篇】IOC/DI注解开发

&#x1f353;系列专栏:Spring系列专栏 &#x1f349;个人主页:个人主页 目录 一、IOC/DI注解开发 1.注解开发定义bean 2.纯注解开发模式 1.思路分析 2.实现步骤 3.注解开发bean作用范围与生命周期管理 1.环境准备 2.Bean的作用范围 3.Bean的生命周期 4.注解开发依赖…

相当Python程序员,选择培训班还是自学?我结合自己的经历谈谈看法

前几天我写了一篇文章&#xff0c;分享了自己当上程序员的经历。然后&#xff0c;我收到了很多小伙伴的提问&#xff0c;都在问同一个问题&#xff0c;即如何选择报培训班还是自学。今天&#xff0c;我结合自己的个人经历&#xff0c;来谈一下个人的看法。 我认为这个问题的第…

Linux线程:死锁

1. 死锁 &#xff08;1&#xff09;概念 死锁&#xff08;DeadLock&#xff09;指两个或两个以上的进程或线程执行时&#xff0c;由于竞争临界资源而造成阻塞的现象&#xff1b;若不干涉&#xff0c;则无法推进下去。 &#xff08;2&#xff09;死锁的原因 ① 竞争临界资源…

06_Uboot顶层Makefile分析_前期所做内容

目录 U-Boot顶层Makefile分析 版本号 MAKEFLAGS变量 命令输出 静默输出 设置编译结果输出目录 代码检查 模块编译 获取主机架构和系统 设置目标架构、交叉编译器和配置文件 调用scripts/Kbuild.include 交叉编译工具变量设置 导出其他变量 U-Boot顶层Makefile分析…

TCP/IP网络编程(一)

TCP/IP网络编程读书笔记 第1章 理解网络编程和套接字1.1 理解网络编程和套接字1.1.1 构建打电话套接字1.1.2 编写 Hello World 套接字程序 1.2 基于Linux的文件操作1.2.1 底层访问和文件描述符1.2.2 打开文件1.2.3 关闭文件1.2.4 将数据写入文件1.2.5 读取文件中的数据1.2.6 文…

操作系统考试复习——第四章 存储器管理 4.1 4.2

存储器的层次结构&#xff1a; 存储器的多层结构&#xff1a; 存储器至少分为三级&#xff1a;CPU寄存器&#xff0c;主存和辅存。 但是一般分为6层为寄存器&#xff0c;高速缓存&#xff0c;主存储器&#xff0c;磁盘缓存&#xff0c;固定磁盘&#xff0c;可移动存储介质。…

( “ 图 “ 之 拓扑排序 ) 207. 课程表 ——【Leetcode每日一题】

❓207. 课程表 难度&#xff1a;中等 你这个学期必须选修 numCourses 门课程&#xff0c;记为 0 到 numCourses - 1 。 在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出&#xff0c;其中 prerequisites[i] [ai, bi] &#xff0c;表示如果要学习课…

自动驾驶中地图匹配定位技术总结

引言 汽车定位是让自动驾驶汽车知道自身确切位置的技术&#xff0c;在自动驾驶系统中担负着相当重要的职责。汽车定位涉及多种传感器类型和相关技术&#xff0c;主要可分为卫星定位、惯性导航定位、地图匹配定位以及多传感器融合定位几大类。其中地图匹配定位技术利用道路物理…

redis使用总结

目录 redis安装与登录redis 持久化RDB(Redis DataBase)AOF(Append Only File)RDB-AOF混合持久纯缓存模式 redis 的 keyredis 的数据类型和常见应用场景StringListHashMapSet集合ZSet有序集合bitmap位图HyperLogLog基数统计GEO 地理空间Stream 流bitfiled redis 事务事务的正常执…

【微机原理】8088/8086微处理器

目录 一、8088/8086的功能结构 1.总线接口部件&#xff08;BIU&#xff09; 2.执行部件&#xff08;EU&#xff09; 二、8088/8086的寄存器结构&#xff08;14个&#xff09; 溢出标志的概念 溢出和进位的区别 8086CPU是Intel系列的16位微处理器&#xff0c;他有16根数据…

servlet技术

什么是Servlet? Servlet 是 javaEE 规范之一. 规范就是接口 Servlet 是 javaWeb三大组件之一 三大组件分别是: Servlet程序, Flter过滤器, Listener监听器Servlet 是运行在服务器上的一个 java 小程序, 他可以接收客户端发送过来的请求, 并响应数据给客户端. 手动实现S…
最新文章