1.JavaScript基本數(shù)據(jù)類型
? number typeof -> number
? boolean typeof -> boolean
? string typeof -> string
? undefined typeof -> undefined
? null typeof -> object
2.全局變量/局部變量
? 全局變量:
? 1.定義在函數(shù)外面的變量闷板,稱為全局變量倾哺;很少用
? 2.定義在函數(shù)內(nèi)部盹兢,沒(méi)有使用var聲明的變量,稱為全局變量末秃。
? 局部變量:
? 方法內(nèi)部莺戒,用var聲明的變量咳秉,稱為局部變量茅撞。
3.使用Array模擬棧結(jié)構(gòu)
var arr = [1, 2, 3];
arr.push(true, false); //push可以向數(shù)組尾部添加一個(gè)或者多個(gè)元素,返回新增元素后數(shù)組的長(zhǎng)度
arr.pop(); //從數(shù)組尾部移除一個(gè)元素稽穆,返回移除的元素 false
4.使用Array模擬隊(duì)列結(jié)構(gòu)
var arr = [1, 2, 3];
arr.push(true); //數(shù)組【1冠王, 2, 3舌镶, true】
arr.shift(); //從數(shù)組頭部移除一個(gè)元素柱彻,返回移除元素 1 數(shù)組【2, 3餐胀, true】
//unshift(1, 2); 向數(shù)組頭部添加一個(gè)或者多個(gè)元素
5.數(shù)組 splice/slice
/**
* splice
* 第一個(gè)參數(shù):起始位置
* 第二個(gè)參數(shù):截取的個(gè)數(shù)(沒(méi)有此參數(shù)表示截除起始位置后面的所有元素)
* 第三個(gè)參數(shù)及以后:追加的新元素(沒(méi)有此參數(shù)表示截除起始位置后n(參數(shù)2的值)個(gè)元素)
*/
var arr = [1, 2, 3, 4, 5];
arr.splice(1, 2, 3, 4, 5);
console.log(arr); //[1, 3, 4, 5, 4, 5]
/**
* slice哟楷,不操作數(shù)組本身
* 第一個(gè)參數(shù):起始位置
* 第二個(gè)參數(shù):結(jié)束位置(不包含結(jié)束的元素)
*/
var arr = [1, 2, 3, 4, 5];
var result = arr.slice(2, 4);
console.log(arr); //[1, 2, 3, 4, 5]
console.log(result); //[3, 4]
6.數(shù)組 concat/join
/**
* concat,合并兩個(gè)數(shù)組,生成一個(gè)新的數(shù)組骂澄,不操作數(shù)組本身
*/
var arr1 = [1, 2, 3, 4, 5];
var arr2 = [true, false]
var result = arr1.concat(arr2);
console.log(arr1); //[1, 2, 3, 4, 5]
console.log(arr2); //[true, false]
console.log(result); //[1, 2, 3, 4, 5, true, false]
/**
* join吓蘑,用指定連接符鏈接數(shù)組所有元素惕虑,不操作數(shù)組本身
* 第一個(gè)參數(shù):起始位置
* 第二個(gè)參數(shù):結(jié)束位置(不包含結(jié)束的元素)
*/
var arr1 = [1, 2, 3, 4, 5];
var result = arr1.join("-");
console.log(arr1); //[1, 2, 3, 4, 5]
console.log(result); //1-2-3-4-5
7.數(shù)組 sort/reverse
var arr = [5, 2, 1, 4, 3];
/**
* sort,正序排列數(shù)組
*/
arr.sort();
console.log(arr);//[1, 2, 3, 4, 5]
var arr1 = [10, 2, 4, 1, 7];
arr1.sort();
console.log(arr1); //[1, 10, 2, 4, 7] 按照字符串來(lái)值比較
//解決方案
arr.sort(function (value1, value2) {
if(value1 < value2){
return -1;
}else if(value1 > value2){
return 1;
}else{
return 0
}
});
/**
* reverse,倒序排列數(shù)組坟冲,不是按照元素大小,而是按照元素索引倒序
*/
arr.reverse();
console.log(arr); //[3, 4, 1, 2, 5]
8.數(shù)組新特性-迭代(every/filter/forEach/map/some)
? every:對(duì)數(shù)組的每一個(gè)元素執(zhí)行一次函數(shù)調(diào)用溃蔫,都返回true健提,則返回true,若有一個(gè)返回false伟叛,則返回false
var arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var result = arr.every(function (value, index, array) {
return value > 2;
});
console.log(result); //false
? filter:對(duì)數(shù)組的每一個(gè)元素執(zhí)行一次函數(shù)調(diào)用私痹,函數(shù)執(zhí)行結(jié)果為false,則把該元素過(guò)濾掉统刮,最后返回過(guò)濾后的結(jié)果
var arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var result = arr.filter(function (value, index, array) {
return value > 2;
});
console.log(result); //[3, 4, 5, 4, 3]
? forEach:對(duì)數(shù)組的每一個(gè)元素執(zhí)行一次函數(shù)調(diào)用紊遵,對(duì)每個(gè)元素進(jìn)行操作,無(wú)返回
var arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
arr.forEach(function (value, index, array) {
console.log(value); //遍歷輸出數(shù)組的每一個(gè)元素
})
? map:對(duì)數(shù)組的每一個(gè)元素執(zhí)行一次函數(shù)調(diào)用侥蒙,返回函數(shù)調(diào)用后的結(jié)果
var arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var result = arr.map(function (value, index, array) {
return value * 2;
});
console.log(result); //[2, 4, 6, 8, 10, 8, 6, 4, 2]
? some:對(duì)數(shù)組的每一個(gè)元素執(zhí)行一次函數(shù)調(diào)用暗膜,若有一個(gè)返回true,則返回true鞭衩,如果都返回false学搜,則返回false
var arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var result = arr.some(function (value, index, array) {
return value >= 5;
});
console.log(result); //true
? reduce:從前往后遍歷娃善,preValue保留上一次函數(shù)運(yùn)算的結(jié)果
var arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var result = arr.reduce(function (preValue, curValue, index, array) {
return preValue + curValue;
});
console.log(result); //25 (1+2+3+4+5+4+3+2+1)
? reduceRight:與reduce相反,從后往前遍歷
9.Object基本方法
? 每一個(gè)object對(duì)象都會(huì)有一下屬性和方法
? --Constructor:構(gòu)造函數(shù)瑞佩,保存著用于創(chuàng)建當(dāng)前對(duì)象的函數(shù)聚磺;
? --hasOwnProperty(propertyName):用于檢測(cè)propertyName屬性是否再當(dāng)前實(shí)例中存在(不包括原型);
? --isPrototypeOf(Object):檢查傳入的對(duì)象是否是另外一個(gè)對(duì)象的原型炬丸;
? --propertyIsEnumerable(propertyName):用于檢查給定的屬性是否能夠使用for iny語(yǔ)句來(lái)枚舉瘫寝;
? --toLocaleString():返回對(duì)象的字符串表示,該字符串與執(zhí)行環(huán)境的地區(qū)對(duì)應(yīng)御雕;
? --toString():返回對(duì)象的字符串顯示矢沿;
? --valueOf():返回對(duì)象的字符串、數(shù)值酸纲、布爾顯示捣鲸;
10.函數(shù)的3中定義方式
//函數(shù)3中定義方式
//1.function語(yǔ)句式,這種方法定義的函數(shù)會(huì)被提前提取編譯
function test1() {
console.log("function語(yǔ)句式");
}
test1(); //function語(yǔ)句式
//2.函數(shù)的直接量
var test2 = function () {
console.log("函數(shù)的直接量");
}
test2(); //函數(shù)的直接量
//3.Function構(gòu)造函數(shù)式闽坡,有動(dòng)態(tài)性栽惶,擁有頂級(jí)作用于
var test3 = new Function("a", "b", "console.log(a+b);");
test3(10, 20); //30
//函數(shù)作用于概念
var k = 1;
function t1() {
var k = 2;
//function test() {return k;} 2
//var test = function () {return k;}; 2
//var test = new Function("return k;"); 1
alert(test());
}
t1();
11.function中的arguments
? 每個(gè)function對(duì)象中都自帶一個(gè)arguments對(duì)象,該對(duì)象存儲(chǔ)了該function的實(shí)際參數(shù)列表疾嗅,arguments是一個(gè)數(shù)組對(duì)象外厂,通過(guò) 方法名.length 可以獲取到方法申明的參數(shù)列表
? arguments.callee 指向函數(shù)自己本身,類似遞歸的時(shí)候推薦使用,仔細(xì)看下面例子
function fact(num) {
if(num <= 1) {
return 1;
} else{
return num * fact(num - 1);
}
}
console.log(fact(5)); //120
var F = fact;
console.log(F(5)); //120
fact = null;
console.log(F(5)); //Uncaught TypeError:fact is not a function
//標(biāo)準(zhǔn)定義
function fact(num) {
if(num <= 1) {
return 1;
} else{
return num * arguments.callee(num - 1);
}
}
12.this
? this對(duì)象是再運(yùn)行時(shí)基于函數(shù)的執(zhí)行環(huán)境綁定的代承,在全局函數(shù)中汁蝶,this等于window,而當(dāng)函數(shù)被作為某個(gè)對(duì)象的方法調(diào)用時(shí)论悴,this等于那個(gè)對(duì)象掖棉。也就是說(shuō),this關(guān)鍵字總指向調(diào)用者膀估。
//this總是指向調(diào)用者
var k = 10;
function test() {
this.k = 20;
}
console.log(test.k); //undefined,因?yàn)閠est函數(shù)還未被調(diào)用
test(); //此處相當(dāng)于window.test(),所以this指向的時(shí)window
console.log(test.k); //undefined
console.log(k); //20,相當(dāng)于window.k
13.call/apply
? call/apply這兩個(gè)方法是每一個(gè)function自帶的成員方法幔亥,他們的作用一樣,都是為function指定執(zhí)行作用域察纯,區(qū)別在于帕棉,call接受的參數(shù)是以參數(shù)列表的形式接受,而apple是將參數(shù)封裝成數(shù)組進(jìn)行接受的饼记。
var color = "red";
var obj = {color:"blue"};
function add(num1, num2) {
console.log(this.color + ":" + (num1 + num2));
}
function call1(obj, num1, num2) {
add.call(obj, num1, num2);
}
function apply1(obj, num1, num2) {
add.apply(obj, [num1, num2]);
}
call1(this, 10, 20); //red:30
apply1(this, 20, 40); //red:60
call1(obj, 10, 20); //blue:30
apply1(obj, 20, 40); //blue:60
14.執(zhí)行環(huán)境
? 執(zhí)行環(huán)境(execution context)是javascript中最為重要的一個(gè)概念香伴。執(zhí)行環(huán)境定義了變量或者函數(shù)有權(quán)訪問(wèn)的其他數(shù)據(jù),決定了他們各自的行為具则。每一個(gè)執(zhí)行環(huán)境都有一個(gè)與之關(guān)聯(lián)的變量對(duì)象即纲,環(huán)境中定義的所有變量和函數(shù)都保存在這個(gè)對(duì)象中。
15.作用域鏈
? 每一個(gè)函數(shù)都有自己的執(zhí)行環(huán)境乡洼,當(dāng)執(zhí)行流進(jìn)一個(gè)函數(shù)時(shí)崇裁,韓式的環(huán)境就會(huì)被推入 一個(gè)環(huán)境棧中妙蔗。而在函數(shù)執(zhí)行之后与帆,棧將其環(huán)境彈出绍载,把控制權(quán)返還給之前的執(zhí)行環(huán)境薄辅。當(dāng)代碼在一個(gè)環(huán)境中執(zhí)行時(shí),會(huì)創(chuàng)建變量對(duì)象的一個(gè)作用域鏈巴比。作用域鏈的用途术奖,是保證對(duì)執(zhí)行環(huán)境有權(quán)訪問(wèn)的所有變量和函數(shù)的有序訪問(wèn)。
16.塊級(jí)作用域
? JavaScript沒(méi)有跨級(jí)作用于的概念轻绞,如下例
function test() {
for(var i = 0; i <= 5; i++){
console.log(i);
}
console.log(i); //6,此處依然能訪問(wèn)到i
}
test();
? 我們可以通過(guò)()()的方式模擬塊級(jí)作用域采记,
function test() {
(function () {
for(var i = 0; i <= 5; i++){
console.log(i);
}
})();
console.log(i); //Uncaught ReferenceError: i is not defined
}
17.閉包
閉包;一個(gè)函數(shù)可以訪問(wèn)另外一個(gè)函數(shù)作用域中的變量政勃,起到保護(hù)變量的作用
? 自己理解:一個(gè)函數(shù)返回另一個(gè)函數(shù)唧龄,返回的函數(shù)有外部作用域的訪問(wèn)權(quán)限
var name = "abc";
var obj = {
name : "efg",
getName: function () {
return function () {
return this.name;
}
}
};
/**
* 這個(gè)方法可以拆解理解的
* var fun = obj.getName() = function(){return this.name}
* fun() = window.fun()
* 所以會(huì)返回外部作用于的name
*/
console.log(obj.getName()()); //abc
//返回obj.name解決方案
var obj1 = {
name:"efg",
getName:function () {
var o = this;
return function () {
return o.name;
}
}
};
console.log(obj1.getName()()); //efg
18.面向?qū)ο?/h4>
18.1.創(chuàng)建面向?qū)ο蟮?種方式
//1.普通方法調(diào)用
function createPerson(name, age, sex) {
var obj = {};
obj.name = name;
obj.age = age;
obj.sex = sex;
return obj;
}
var person = createPerson("zhangsan", 20, "男");
console.log(person.name + ":" + person.age + ":" + person.sex); //zhangsan:20:男
//2.構(gòu)造函數(shù)創(chuàng)建,這種方式,函數(shù)名都是首字母大寫
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
var person = new Person("lisi", 25, "男");
console.log(person.name + ":" + person.age + ":" + person.sex); //lisi:25:男
//3.通過(guò)call/apply的形式調(diào)用
var person = {};
Person.apply(person, ["wangwu", 30, "女"]);
console.log(person.name + ":" + person.age + ":" + person.sex); //wangwu:30:女
18.2.原型(prototype)
//1.普通方法調(diào)用
function createPerson(name, age, sex) {
var obj = {};
obj.name = name;
obj.age = age;
obj.sex = sex;
return obj;
}
var person = createPerson("zhangsan", 20, "男");
console.log(person.name + ":" + person.age + ":" + person.sex); //zhangsan:20:男
//2.構(gòu)造函數(shù)創(chuàng)建,這種方式,函數(shù)名都是首字母大寫
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
var person = new Person("lisi", 25, "男");
console.log(person.name + ":" + person.age + ":" + person.sex); //lisi:25:男
//3.通過(guò)call/apply的形式調(diào)用
var person = {};
Person.apply(person, ["wangwu", 30, "女"]);
console.log(person.name + ":" + person.age + ":" + person.sex); //wangwu:30:女
? 原型(prototype)奸远;每一個(gè)函數(shù)對(duì)象都有一個(gè)prototype屬性既棺,該屬性是一個(gè)指針,指向一個(gè)對(duì)象懒叛,這個(gè)對(duì)象的用途是將特定的屬性和方法封裝起來(lái)丸冕,共實(shí)例對(duì)象共享使用。
function Person() {}
Person.prototype.name = "zhangsan";
Person.prototype.age = 20;
Person.prototype.sayName = function () {
console.log(this.name);
};
var p1 = new Person();
p1.name = "lisi";
var p2 = new Person();
p2.name = "wangwu";
p1.sayName(); //lisi
p2.sayName(); //wangwu
console.log(p1.sayName == p2.sayName); //true
console.log(Person.prototype.isPrototypeOf(p1)); //true 判斷是否是某對(duì)象的原型
console.log(Object.getPrototypeOf(p1)); //返回Person.prototype對(duì)象
? 構(gòu)造函數(shù)薛窥,原型對(duì)象胖烛,實(shí)例對(duì)象三者的關(guān)系
? 1.構(gòu)造函數(shù).prototype = 原型對(duì)象
? 2.原型對(duì)象.constructor = 構(gòu)造函數(shù)(模板)
? 3.原型對(duì)象.isPrototypeOf(實(shí)例對(duì)象) 判斷實(shí)例對(duì)象的原型是否是當(dāng)前對(duì)象
18.3.原型的使用
18.3.1.簡(jiǎn)單原型模式
? 該模式要遵循的原則式創(chuàng)建對(duì)象必須放在原型后面,否則創(chuàng)建的對(duì)象無(wú)法訪問(wèn)到原型內(nèi)的屬性或方法
function Person() {}
Person.prototype = {
name:'z3',
age:20,
sayName:function () {
console.log(this.name);
}
}
//定義Person.prototype的構(gòu)造函數(shù)為Person,使用這種方法指定構(gòu)造函數(shù)诅迷,for-in的時(shí)候無(wú)法獲取到constructor
Object.defineProperty(Person.prototype, "constructor", {
enumerable:false,
value:Person
})
var p = new Person();
p.sayName(); //z3
console.log(Person.prototype.constructor); //function Person(){}
18.3.2.組合使用構(gòu)造函數(shù)和原型模式
? 由于上述方式所有屬性/方法對(duì)所有對(duì)象都是共享的佩番,有一個(gè)明顯的缺點(diǎn),當(dāng)屬性是應(yīng)用數(shù)據(jù)類型時(shí)竟贯,A對(duì)象對(duì)這個(gè)數(shù)組進(jìn)行了push操作答捕,B對(duì)象去訪問(wèn)時(shí)得到的時(shí)A對(duì)象操作后的結(jié)果逝钥。通過(guò)組合使用構(gòu)造函數(shù)和原型模式可以有效解決這個(gè)問(wèn)題
function Person(name, age, friends) {
this.name = name;
this.age = age;
this.friends = friends;
}
Person.prototype = {
constructor : Person,
sayName : function () {
console.log(this.name);
}
}
var p1 = new Person('z1', 20, ["aaa", 'bbb']);
p1.friends.push('zzz');
var p2 = new Person('z2', 22, ['ccc', 'ddd']);
p2.friends.push('yyyy');
p1.sayName(); //z1
p2.sayName(); //z2
console.log(p1.friends); //["aaa", "bbb", "zzz"]
console.log(p2.friends); //["ccc", "ddd", "yyyy"]
18.3.3.動(dòng)態(tài)原型模式
? 該模式把所有的屬性和方法封裝到一起,代碼更加簡(jiǎn)潔屑那,如下方式定義,sayName只會(huì)被創(chuàng)建一次
function Person(name, age) {
this.name = name;
this.age = age;
if(typeof this.sayName != "function"){
Person.prototype.sayName = function () {
console.log(this.name);
}
}
}
var p1 = new Person('z1', 20);
var p2 = new Person('z3', 22);
p1.sayName(); //z1
p2.sayName(); //z3
18.3.4.穩(wěn)妥構(gòu)造函數(shù)式
? 適合在非常安全的環(huán)境中使用艘款,他沒(méi)有公共屬性持际,不能使用this對(duì)象,同時(shí)創(chuàng)建的時(shí)候也不使用new,這種方法類似與java中的private,所有屬性都無(wú)法通過(guò)obj.xxx的方式獲取哗咆,必須通過(guò)對(duì)應(yīng)的方法獲取蜘欲。
function Person() {
var obj = {};
var name = 'z1';
var age = 20;
obj.sayName = function () {
console.log(name);
}
return obj;
}
var p = Person();
p.sayName(); //z1
19.繼承
? JavaScript通過(guò)讓子類對(duì)象的原型指向父類對(duì)象的方式實(shí)現(xiàn)繼承
19.1.原型繼承
? 特點(diǎn):即繼承了父類的模板,又繼承了原型對(duì)象
function Sup(name){
this.name = name;
}
function Sub(age) {
this.age = age;
}
var sup = new Sup('z3');
Sub.prototype = sup;
var sub = new Sub(20);
console.log(sub.name); //z3
console.log(sub.age); //20
console.log(sup.isPrototypeOf(sub)); //true
console.log(Sub.prototype.constructor); //function Sup(name){this.name = name;}
console.log(sub instanceof Sub); //true
console.log(sub instanceof Sup); //true
19.2類繼承
? 特點(diǎn):只繼承模板晌柬,不繼承原型對(duì)象姥份,又稱借用構(gòu)造函數(shù)方式繼承
function Person(name, age) {
this.name = name;
this.age = age;
}
function Boy(name, age, sex) {
Person.call(this, name, age);
this.sex = sex;
}
var boy = new Boy('z3', 20, '男');
console.log(boy.name + " : " + boy.age + " : " + boy.sex); //z3 : 20 : 男
console.log(boy instanceof Boy); //true
console.log(boy instanceof Person); //false
console.log(Boy.prototype.constructor); //Boy(name, age, sex) {Person.call(this, name, age);this.sex = sex;}
19.3混合繼承
function Person(name, age) {
this.name = name;
this.age = age;
}
function Boy(name, age, sex) {
Person.call(this, name, age);
this.sex = sex;
}
Boy.prototype = new Person();
var boy = new Boy('z3', 20, '男');
console.log(boy.name + " : " + boy.age + " : " + boy.sex); //z3 : 20 : 男
console.log(boy instanceof Boy); //true
console.log(boy instanceof Person); //true
console.log(Boy.prototype.constructor); //Person(name, age) {this.name = name;this.age = age; }
20.Ajax
20.1創(chuàng)建XHR
目前Javascript主流的都是通過(guò)Ajax技術(shù)進(jìn)行網(wǎng)絡(luò)請(qǐng)求的郭脂,Ajax可以不需要刷新頁(yè)面的同時(shí)與服務(wù)器進(jìn)行交互,提高用戶體驗(yàn)澈歉,Ajax的核心是XMLHttpRequest展鸡,目前主流的瀏覽器都支持原生的XHR,但是IE7以前使用的是MSXML庫(kù)中的XHR對(duì)象埃难,所以為了兼容性莹弊,我們可以通過(guò)一下方式獲取XHR
function createXHR() {
if(typeof XMLHttpRequest != "undefined"){
return new XMLHttpRequest();
}else if(typeof ActiveXObject != "undefined"){
if(typeof arguments.callee.activeXString != "string"){
var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"];
var i, len;
for(i = 0, len = versions.length; i < len; i++){
try{
new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
break;
}catch (ex){
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
}else{
throw new Error("No XHR object available");
}
}
20.2同步請(qǐng)求
var xhr = createXHR();
xhr.open("get",
"https://accountv3-api.fclassroom.cn/checkVersion.json?jike-client-from=APP&versionType=21&category=20&versionNo=356",
false);
xhr.send(null);
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
console.log(xhr.responseText);
}else{
console.log("Request was unsuccessful : " + xhr.status);
}
20.3異步請(qǐng)求
var xhr = createXHR();
xhr.onreadystatechange = function () {
/**
* readyState
* 0:未初始化
* 1:啟動(dòng)
* 2:發(fā)送
* 3:接收
* 4:完成
*/
if(xhr.readyState == 4){
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
console.log(xhr.responseText);
}else{
console.log("Request was unsuccessful : " + xhr.status);
}
}
}
xhr.open("get",
"https://accountv3-api.fclassroom.cn/checkVersion.json?jike-client-from=APP&versionType=21&category=20&versionNo=356",
true);
xhr.send(null);
20.4Get/Post
get請(qǐng)求與上述方式一樣,如果需要為請(qǐng)求添加自己的header涡尘,可以通過(guò)XHR的setRequestHeader(name,value)進(jìn)行設(shè)置忍弛,這個(gè)方法的調(diào)用必須在open之后,send之前考抄。
post請(qǐng)求可以通過(guò)FormData來(lái)承載需要提交的數(shù)據(jù)
var xhr = createXHR();
xhr.onreadystatechange = function () {
if(xhr.readyState == 4){
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
console.log(xhr.responseText);
}else{
console.log("Request was unsuccessful : " + xhr.status);
}
}
}
xhr.open("post",
"https://accountv3-api.fclassroom.cn/checkVersion.json",
true);
var formData = new FormData();
formData.append("jike-client-from", "APP");
formData.append("versionType", "21");
formData.append("category", "20");
formData.append("versionNo", "356");
xhr.send(formData);