前者是切割成数组的形式,后者是将数组转换成字符串 1.执行顺序不一样、 var ev = ev || window.event 功能一样, 都是将当前函数作为指定对象的方法执行, 即函数中的this是指定对象 element.appendChild() 内置对象为Object, Array, Function, Date, Math等 window.onload 是在dom文档树加载完和所有文件加载完之后执行一个函数document.ready原生中没有这个方法,jquery中有 $().ready(function),在dom文档树加载完之后执行一个函数(注意,这里面的文档树加载完不代表全部文件加载完)。 前者会自动转换类型 一段脚本(ajax)只能读取来自于同一来源的窗口和文档的属性,这里的同一来源指的是主机名、协议和端口号的组合 javaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML网页上使用,用来给HTML网页增加动态功能。JavaScript兼容于ECMA标准,因此也称为ECMAScript。 var dom = document.getElementById(“ID”); 直接在DOM里绑定事件: 在JS里通过onclick绑定:xxx.onclick = test alert(stringArray.join(“”)) 如果foo存在,值不变,否则把bar的值赋给foo。 1)创建新节点 var _变量=NaN; B、var 0bj = []; C、var obj = //; D、var obj = {}; 答案( B C ) A、var a=undefined; b=NaN A 34 B、35 C、36 D、37 答案( B ) A. for(vari=0;i< form1.elements.length;i++) { A. window.status=”已经选中该文本框” A.var obj = (); A.with A.null instanceof Object 对象:window, document, location, screen, history, navigator document.getElementById 根据元素id查找元素 优点: 内存泄漏指任何对象在您不再拥有或需要它之后仍然存在。 动态创建script标签,回调函数 在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再 被第3者所引用,那么这两个互相引用的对象也会被回收。因为函数a被b引用,b又被a外的c引用,这就是为什么 函数a执行后不会被回收的原因。 IE6下这个问题是因为默认的行高造成的,解决的方法也有很多,例如: 1、标签之中直接添加 οnclick=“fun()”; ReadOnly和Disabled的作用是使用户不能够更改表单域中的内容. 简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面。这其中最关键的一步就是从服务器获得请求数据。要清楚这个过程和原理,我们必须对 XMLHttpRequest有所了解。 因为你不知道哪一天浏览器或javascript本身就会实现这个方法,而且和你扩展的实现有不一致的表现。到时候你的javascript代码可能已经在无数个页面中执行了数年,而浏览器的实现导致所有使用扩展原型的代码都崩溃了。。。 90.下面这段代码想要循环输出结果01234,请问输出结果是否正确,如果不正确,请说明为什么,并修改循环内的代码使其输出正确结果 A. window.opener属性本身就是指向window对象 A: 跨域问题能通过JsonP方案解决 93.错误的是 c A: Ajax本质是XMLHttpRequest 有误差,应该比准确结果偏大。 一般我会将小数变为整数来处理。当前之前遇到这个问题时也上网查询发现有人用try catch return写了一个函数,当然原理也是一致先转为整数再计算。 (1) window.event: (2) 获取事件源 (3) 添加,去除事件 (4) 获取标签的自定义属性 101.《正则》写出正确的正则表达式匹配固话号,区号3-4位,第一位为0,中横线,7-8位数字,中横线,3-4位分机号格式的固话号 ^[0]d{2,3}-d{7,8}-d{3,4}$ 102.《算法》 一下A,B可任选一题作答,两题全答加分 114.Ajax 是什么? 如何创建一个Ajax? 分为4个步骤: 116.请说出三种减低页面加载时间的方法 1、压缩css、js文件 117.HTTP状态码都有那些。 200 OK //客户端请求成功 相同点:两个方法产生的作用是完全一样的 writable:这个属性的值是否可以改。 (1) 减少http请求次数:CSS Sprites, JS、CSS源码压缩、图片大小控制合适;网页Gzip,CDN托管,data缓存 ,图片服务器。js基础
一、JS基础
alert(typeof [1, 2]); //object alert(typeof 'leipeng'); //string var i = true; alert(typeof i); //boolean alert(typeof 1); //number var a; alert(typeof a); //undefined function a(){;}; alert(typeof a) //function
强制(parseInt(),parseFloat(),Number()) 隐式(== ,!!)
push()尾部添加 pop()尾部删除 unshift()头部添加 shift()头部删除 map() : 遍历数组中的元素, 返回一个新数组(包含回调函数返回的数据) filter():遍历数组中的元素, 返回一个新数组(包含回调函数返回true的元素)
普通添加事件的方法: var btn = document.getElementById("hello"); btn.onclick = function(){ alert(1); } btn.onclick = function(){ alert(2); } 执行上面的代码只会alert 2 事件绑定方式添加事件: var btn = document.getElementById("hello"); btn.addEventListener("click",function(){ alert(1); },false); btn.addEventListener("click",function(){ alert(2); },false); 执行上面的代码会先alert 1 再 alert 2 普通添加事件的方法不支持添加多个事件,最下面的事件会覆盖上面的,而事件绑定(addEventListener)方式添加事件可以添加多个。 addEventListener不兼容低版本IE 普通事件无法取消 addEventLisntener还支持事件冒泡+事件捕获
2.参数不一样
3.事件加不加on
4.this指向问题
document.documentElement.clientWidth || document.body.clientWidth
var target = ev.srcElement||ev.target
call(thisObj,arg1,arg2…) //将所有参数一个一个传递进去
apply(thisObj,[argArray]) //将所有参数放在数组中传入
//使用构造函数+原型的组合模式 function Person( age, name ){ this.age = age; this.name = name; } Person.prototype.show = function(){ alert('父级方法'); } function Worker(age,name,job){ Person.apply( this, arguments); this.job = job; } Worker.prototype = new Person(); var Person = new Person(14,'张三 '); var Worker = new Worker (25,'李四','程序员');
//阻止事件冒泡 if(typeof ev.stopPropagation=='function') { //标准的 ev.stopPropagation(); } else { //非标准IE window.event.cancelBubble = true; } //阻止事件默认行为 return false
element.insertBefore()
element.replaceChild()
element.removeChild()
宿主为浏览器自带的window 等
(document).ready要比window.onload先执行window.onload只能出来一次,(document).ready可以出现多次
后者不会
基本特点
跨平台特性,在绝大多数浏览器的支持下,可以在多种平台下运行(如Windows、Linux、Mac、Android、iOS等)。
基本数据类型:String,boolean,Number,Undefined, Null 引用数据类型:Object, Array, Function 那么问题来了,如何判断某变量是否为数组数据类型? 方法一.判断其是否具有“数组性质”,如slice()方法。可自己给该变量定义slice方法,故有时会失效 方法二.obj instanceof Array 在某些IE版本中不正确 方法三.方法一二皆有漏洞,在ECMA Script5中定义了新方法Array.isArray(), 保证其兼容性,最好的方法如下: if(typeof Array.isArray==="undefined") { Array.isArray = function(arg){ return Object.prototype.toString.call(arg)==="[object Array]" }; }
document.getElementById(ID).value
var domList = document.getElementsByTagName(‘input’) var checkBoxList = []; var len = domList.length; //缓存到局部变量 for (var i=0;i<len;i++) { if (domList[i].type == ‘checkbox’) { checkBoxList.push(domList[i]); } }
dom.innerHTML = “xxxx”
dom.style.color = “#000”
通过事件添加进行绑定:addEventListener(xxx, ‘click’, test)
那么问题来了,Javascript的事件流模型都有什么?
“事件冒泡”:事件开始由最具体的元素接受,然后逐级向上传播
“事件捕捉”:事件由最不具体的节点先接收,然后逐级向下,一直到最具体的
“DOM事件流”:三个阶段:事件捕捉,目标阶段,事件冒泡
var a; alert(typeof a); // undefined alert(b); // 报错 解释:Undefined是一个只有一个值的数据类型,这个值就是“undefined”,在使用var声明变量但并未对其赋值进行初始化时,这个变量的值就是undefined。而b由于未声明将报错。注意未申明的变量和声明了未赋值的是不一样的。
var a = null; alert(typeof a); //object 解释:null是一个只有一个值的数据类型,这个值就是null。表示一个空指针对象,所以用typeof检测会返回”object”。 看下列代码,输出什么?解释原因。 var undefined; undefined == null; // true 1 == true; // true 2 == true; // false 0 == false; // true 0 == ''; // true NaN == NaN; // false [] == false; // true [] == ![]; // true undefined与null相等,但不恒等(===) 一个是number一个是string时,会尝试将string转换为number 尝试将boolean转换为number,0或1 尝试将Object转换成number或string,取决于另外一个对比量的类型 所以,对于0、空字符串的判断,建议使用 “===” 。“===”会先判断两边的值类型,类型不匹配时为false。 那么问题来了,看下面的代码,输出什么,foo的值为什么? var foo = "11"+2-"1"; console.log(foo); console.log(typeof foo); 执行完后foo的值为111,foo的类型为String。
var a = new Object(); a.value = 1; b = a; b.value = 2; alert(a.value); 答案:2(考察引用数据类型细节)
function combo(msg){ var arr=msg.split("-"); for(var i=1;i<arr.length;i++){ arr[i]=arr[i].charAt(0).toUpperCase()+arr[i] .substr(1,arr[i].length-1); } msg=arr.join(""); return msg; }
numberArray.reverse()
numberArray.sort(function(a,b){return b-a})
var d = new Date(); // 获取年,getFullYear()返回4位的数字 var year = d.getFullYear(); // 获取月,月份比较特殊,0是1月,11是12月 var month = d.getMonth() + 1; // 变成两位 month = month < 10 ? '0' + month : month; // 获取日 var day = d.getDate(); day = day < 10 ? '0' + day : day; alert(year + '-' + month + '-' + day);
"<tr><td>{$id}</td><td>{$id}_{$name}</td></tr>".replace(/{$id}/g, '10').replace(/{$name}/g, 'Tony');
function escapeHtml(str) { return str.replace(/[<>”&]/g, function(match) { switch (match) { case “<”: return “<”; case “>”: return “>”; case “&”: return “&”; case “””: return “"”; } }); }
短路表达式:作为”&&”和”||”操作符的操作数表达式,这些表达式在进行求值时,只要最终的结果已经可以确定是真或假,求值过程便告终止,这称之为短路求值。
var foo = 1; (function(){ console.log(foo); var foo = 2; console.log(foo); })() 答案:输出undefined 和 2。上面代码相当于: var foo = 1; (function(){ var foo; console.log(foo); //undefined foo = 2; console.log(foo); // 2; })() 函数声明与变量声明会被JavaScript引擎隐式地提升到当前作用域的顶部,但是只提升名称不会提升赋值部分。
function randomNub(aArray, len, min, max) { if (len >= (max - min)) { return '超过' + min + '-' + max + '之间的个数范围' + (max - min - 1) + '个的总数'; } if (aArray.length >= len) { aArray.sort(function(a, b) { return a - b }); return aArray; } var nowNub = parseInt(Math.random() * (max - min - 1)) + (min + 1); for (var j = 0; j < aArray.length; j++) { if (nowNub == aArray[j]) { randomNub(aArray, len, min, max); return; } } aArray.push(nowNub); randomNub(aArray, len, min, max); return aArray; } var arr=[]; randomNub(arr,10,10,100);
var array1 = ['a','b','c']; var bArray = ['d','e','f']; var cArray = array1.concat(bArray); cArray.splice(1,1);
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
2)添加、移除、替换、插入
appendChild() //添加
removeChild() //移除
replaceChild() //替换
insertBefore() //插入
3)查找
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值
getElementById() //通过元素Id,唯一性
function serilizeUrl(url) { var urlObject = {}; if (/?/.test(url)) { var urlString = url.substring(url.indexOf("?") + 1); var urlArray = urlString.split("&"); for (var i = 0, len = urlArray.length; i < len; i++) { var urlItem = urlArray[i]; var item = urlItem.split("="); urlObject[item[0]] = item[1]; } return urlObject; } return null; }
当使用RegExp()构造函数的时候,不仅需要转义引号(即”表示”),并且还需要双反斜杠(即\表示一个)。使用正则表达字面量的效率更高。 邮箱的正则匹配: var regMail = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/;
for(var i=1;i<=3;i++){ setTimeout(function(){ console.log(i); },0); }; 答案:4 4 4。 原因:回调函数是在for结束之后才运行的。追问,如何让上述代码输出1 2 3? for(var i=1;i<=3;i++){ setTimeout((function(j){ //改成立即执行函数 console.log(j); })(i),0); };
if (!String.prototype.trim) { String.prototype.trim = function() { return this.replace(/^s+/, "").replace(/s+$/,""); } } //测试 var str = " tn test string ".trim(); alert(str == "test string"); // alerts "true"
B、var a= ‘123’; b=NaN
C、var a =undefined , b =NaN
var a=NaN , b=‘undefined’
if(form1.elements.type==”text”)
form1.elements.value=””;}
B. for(vari=0;i<document.forms.length;i++) {
if(forms[0].elements.type==”text”)
forms[0].elements.value=””;
}
C. if(document.form.elements.type==”text”)
form.elements.value=””;
D. for(vari=0;i<document.forms.length; i++){
for(var j=0;j<document.forms.elements.length; j++){
if(document.forms.elements[j].type==”text”)
document.forms.elements[j].value=””;
}
}
B. document.status=”已经选中该文本框”
C. window.screen=”已经选中该文本框”
D. document.screen=”已经选中该文本框”
B.var obj = [];
C.var obj = {};
D.var obj = //;
B.parent
C.class
D.void
B.null === undefined
C.null == undefined
D.NaN == NaN
var a=10, b=20 , c=30; ++a; a++; e=++a + (++b) + (c++) + a++; alert(e); 弹出提示对话框:77
function DateDemo(){ var d, s="今天日期是:"; d = new Date(); s += d.getMonth() +1+ "/"; s += d.getDate() + "/"; s += d.getFullYear(); return s; } 结果:今天日期是:7/21/2016
for(i=0, j=0; i<10, j<6; i++, j++){ k = i + j;} 结果:10
var arr = new Array(1 ,3 ,5); arr[4]='z'; arr2 = arr.reverse(); arr3 = arr.concat(arr2); alert(arr3); 弹出提示对话框:z,,5,3,1,z,,5,3,1
var str = “<div>这里是div<p>里面的段落</p></div>”; <scripttype=”text/javascript”> var reg = /</?w+/?>/gi; var str = “<div>这里是div<p>里面的段落</p></div>”; alert(str.replace(reg,”")); </script> 截取字符串abcdefg的efg alert('abcdefg'.substring(4));
方法:alert(), confirm(), prompt(), open(), close()
document.getElementByName 根据元素name查找元素
document.getElementTagName 根据指定的元素名查找元素
第一种(函数声明): function sum1(num1,num2){ return num1+num2; } 第二种(函数表达式): var sum2 = function(num1,num2){ return num1+num2; } 第三种(函数对象方式): var sum3 = new Function("num1","num2","return num1+num2");
1、var obj = {};(使用json创建对象) 如:obj.name = '张三'; obj.action = function () { alert('吃饭'); }; 2、var obj = new Object();(使用Object创建对象) 如:obj.name = '张三'; obj.action = function () { alert('吃饭'); }; 3、通过构造函数创建对象。 (1)、使用this关键字 如:var obj = function (){ this.name ='张三'; this.age = 19; this.action = function () { alert('吃饭'); }; } (2)、使用prototype关键字 如:function obj (){} obj.prototype.name ='张三'; obj.prototype.action=function () { alert('吃饭'); }; 4、使用内置对象创建对象。 如:var str = new String("实例初始化String"); var str1 = "直接赋值的String"; var func = new Function("x","alert(x)");//示例初始化func var obj = new Object();//示例初始化一个Object
缺点:
垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为 0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收。
var str = 'asdfssaaasasasasaa'; var json = {}; for (var i = 0; i < str.length; i++) { if(!json[str.charAt(i)]){ json[str.charAt(i)] = 1; }else{ json[str.charAt(i)]++; } }; var iMax = 0; var iIndex = ''; for(var i in json){ if(json[i]>iMax){ iMax = json[i]; iIndex = i; } } alert('出现次数最多的是:'+iIndex+'出现'+iMax+'次');
function getStyle(obj,attr,value) { if(!value) { if(obj.currentStyle) { return obj.currentStyle(attr); } else{ obj.getComputedStyle(attr,false); } } else { obj.style[attr] = value; } }
答:当内部函数使用了外部函数的局部变量时, 产生的一个对象(包含了所有使用了的变量) 作用: 在函数执行完后, 局部变量还会存在 function outer(){ var num = 1; function inner(){ var n = 2; alert(n + num); } return inner; } var r = outer(); r();
Ajax是页面无刷新请求数据操作
//思路:先将字符串转换为数组 split(),利用数组的反序函数 reverse()颠倒数组,再利用 jion() 转换为字符串 var str = '12345678'; str = str.split('').reverse().join(''); 将数字 12345678 转化成 RMB形式 如: 12,345,678 //思路:先将数字转为字符, str= str + '' ; //利用反转函数,每三位字符加一个 ','最后一位不加; re()是自定义的反转函数,最后再反转回去! function re(str) { str += ''; return str.split("").reverse().join(""); } function toRMB(num) { var tmp=''; for (var i = 1; i <= re(num).length; i++) { tmp += re(num)[i - 1]; if (i % 3 == 0 && i != re(num).length) { tmp += ','; } } return re(tmp); }
//思路:5个不同的数,每生成一次就和前面的所有数字相比较,如果有相同的,则放弃当前生成的数字! var num1 = []; for(var i = 0; i < 5; i++){ num1[i] = Math.floor(Math.random()*10) + 1; //范围是 [1, 10] for(var j = 0; j < i; j++){ if(num1[i] == num1[j]){ i--; } } }
//思路:每遍历一次就和之前的所有做比较,不相等则放入新的数组中! //这里用的原型 个人做法; Array.prototype.unique = function(){ var len = this.length, newArr = [], flag = 1; for(var i = 0; i < len; i++, flag = 1){ for(var j = 0; j < i; j++){ if(this[i] == this[j]){ flag = 0; //找到相同的数字后,不执行添加数据 } } flag ? newArr.push(this[i]) : ''; } return newArr; } 方法二: var arr=[1,2,3,3,4,4,5,5,6,1,9,3,25,4]; Array.prototype.unique2 = function() { var n = []; //一个新的临时数组 for(var i = 0; i < this.length; i++) //遍历当前数组 { //如果当前数组的第i已经保存进了临时数组,那么跳过, //否则把当前项push到临时数组里面 if (n.indexOf(this[i]) == -1) n.push(this[i]); } return n; } var newArr2=arr.unique2(arr); alert(newArr2); //输出1,2,3,4,5,6,9,25 阶乘函数; //原型方法 Number.prototype.N = function(){ var re = 1; for(var i = 1; i <= this; i++){ re *= i; } return re; } var num = 5; alert(num.N());
function f1(){ var tmp = 1; this.x = 3; console.log(tmp); //A console.log(this.x); //B } var obj = new f1(); //1 console.log(obj.x) //2 console.log(f1()); //3 这道题让我重新认识了对象和函数,首先看代码(1),这里实例话化了 f1这个类。相当于执行了 f1函数。所以这个时候 A 会输出 1, 而 B 这个时候的 this 代表的是 实例化的当前对象 obj B 输出 3.。 代码(2)毋庸置疑会输出 3, 重点 代码(3)首先这里将不再是一个类,它只是一个函数。那么 A输出 1, B呢?这里的this 代表的其实就是window对象,那么this.x 就是一个全局变量 相当于在外部 的一个全局变量。所以 B 输出 3。最后代码由于f没有返回值那么一个函数如果没返回值的话,将会返回 underfined ,所以答案就是 : 1, 3, 3, 1, 3, underfined 。 下面输出多少? var o1 = new Object(); var o2 = o1; o2.name = "CSSer"; console.log(o1.name); 如果不看答案,你回答真确了的话,那么说明你对javascript的数据类型了解的还是比较清楚了。js中有两种数据类型,分别是:基本数据类型和引用数据类型(object Array)。对于保存基本类型值的变量,变量是按值访问的,因为我们操作的是变量实际保存的值。对于保存引用类型值的变量,变量是按引用访问的,我们操作的是变量值所引用(指向)的对象。答案就清楚了: //CSSer; 再来一个 function changeObjectProperty (o) { o.siteUrl = "https://www.csser.com/"; o = new Object(); o.siteUrl = "https://www.popcg.com/"; } var CSSer = new Object(); changeObjectProperty(CSSer); console.log(CSSer.siteUrl); // “https://www.csser.com/” 如果CSSer参数是按引用传递的,那么结果应该是"https://www.popcg.com/",但实际结果却仍是"https://www.csser.com/"。事实是这样的:在函数内部修改了引用类型值的参数,该参数值的原始引用保持不变。我们可以把参数想象成局部变量,当参数被重写时,这个变量引用的就是一个局部变量,局部变量的生存期仅限于函数执行的过程中,函数执行完毕,局部变量即被销毁以释放内存。 (补充:内部环境可以通过作用域链访问所有的外部环境中的变量对象,但外部环境无法访问内部环境。每个环境都可以向上搜索作用域链,以查询变量和函数名,反之向下则不能。)
var a = 6; setTimeout(function () { var a = 666; alert(a); // 输出666, }, 1000); 因为var a = 666;定义了局部变量a,并且赋值为666,根据变量作用域链, 全局变量处在作用域末端,优先访问了局部变量,从而覆盖了全局变量 。 var a = 6; setTimeout(function () { alert(a); // 输出undefined var a = 666; }, 1000); 因为var a = 666;定义了局部变量a,同样覆盖了全局变量,但是在alert(a);之前 a并未赋值,所以输出undefined。 var a = 6; setTimeout(function(){ alert(a); var a = 66; }, 1000); a = 666; alert(a); // 666, undefined; 记住: 异步处理,一切OK 声明提前
function setN(obj){ obj.name='屌丝'; obj = new Object(); obj.name = '腐女'; }; var per = new Object(); setN(per); alert(per.name); //屌丝 内部
var n = 0.3,m = 0.2, i = 0.2, j = 0.1; alert((n - m) == (i - j)); //false alert((n-m) == 0.1); //false alert((i-j)==0.1); //true 加减运算 alert('5'+3); //53 string alert('5'+'3'); //53 string alert('5'-3); //2 number alert('5'-'3'); //2 number
overflow:hidden | zoom:0.08 | line-height:1px
function foo(){ foo.a = function(){alert(1)}; this.a = function(){alert(2)}; a = function(){alert(3)}; var a = function(){alert(4)}; }; foo.prototype.a = function(){alert(5)}; foo.a = function(){alert(6)}; foo.a(); //6 var obj = new foo(); obj.a(); //2 foo.a(); //1 输出结果 var a = 5; function test(){ a = 0; alert(a); alert(this.a); //没有定义 a这个属性 var a; alert(a) } test(); // 0, 5, 0 new test(); // 0, undefined, 0 //由于类它自身没有属性a, 所以是undefined
new function(s){ if(!arguments.length||!s) return null; if(""==s) return 0; var l=0; for(var i=0;i<s.length;i++){ if(s.charCodeAt(i)>255) l+=2; else l+=1; //charCodeAt()得到的是unCode码 } //汉字的unCode码大于 255bit 就是两个字节 alert(l); }("hello world!"); 结果是: var bool = !!2; alert(bool);//true; 双向非操作可以把字符串和数字转换为布尔值。
var reg = /^[a-zA-Z_][a-zA-Z0-9_]{5,20}/, name1 = 'leipeng', name2 = '0leipeng', name3 = '你好leipeng', name4 = 'hi'; alert(reg.test(name1)); alert(reg.test(name2)); alert(reg.test(name3)); alert(reg.test(name4));
2、JS添加 Eobj.onclick = method;
3、绑定事件 IE: obj.attachEvent(‘onclick’, method);
FF: obj.addEventListener(‘click’, method, false);
BOM对象有哪些,列举window对象?
1、window对象 ,是JS的最顶层对象,其他的BOM对象都是window对象的属性;
2、document对象,文档对象;
3、location对象,浏览器当前URL信息;
4、navigator对象,浏览器本身信息;
5、screen对象,客户端屏幕信息;
6、history对象,浏览器访问历史信息;
//说明:outerHTML其实就是innerHTML再加上本身; Object.prototype.outerHTML = function(){ var innerCon = this.innerHTML, //获得里面的内容 outerCon = this.appendChild(innerCon); //添加到里面 alert(outerCon); } 演示代码: <!doctype html> <html> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="outer"> hello </div> <script> Object.prototype.outerHTML = function(){ var innerCon = this.innerHTML, //获得里面的内容 outerCon = this.appendChild(innerCon); //添加到里面 alert(outerCon); } function $(id){ return document.getElementById(id); } alert($('outer').innerHTML); alert($('outer').outerHTML); </script> </body> </html>
//定义个父母类,注意:类名都是首字母大写的哦! function Parent(name, money){ this.name = name; this.money = money; this.info = function(){ alert('姓名: '+this.name+' 钱: '+ this.money); } } //定义孩子类 function Children(name){ Parent.call(this, name); //继承 姓名属性,不要钱。 this.info = function(){ alert('姓名: '+this.name); } } //实例化类 var per = new Parent('parent', 800000000000); var chi = new Children('child'); per.info(); chi.info();
bind: 绑定事件,对新添加的事件不起作用,方法用于将一个处理程序附加到每个匹配元素的事件上并返回jQuery对象。 live: 方法将一个事件处理程序附加到与当前选择器匹配的所有元素(包含现有的或将来添加的)的指定事件上并返回jQuery对象。 delegate: 方法基于一组特定的根元素将处理程序附加到匹配选择器的所有元素(现有的或将来的)的一个或多个事件上。
var foo = "11"+2-"1"; console.log(foo); console.log(typeof foo); 执行完后foo的值为111,foo的类型为Number。 看下列代码,输出什么? var a = new Object(); a.value = 1; b = a; b.value = 2; alert(a.value); 执行完后输出结果为2
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="container" style="display: table;width: 100%;"> <div id="left" style="background-color: red;display: table-cell;"> 内容<br/> 内容<br/> 内容<br/> 内容<br/> 内容<br/> 内容<br/> </div> <div style="display:table-cell;"></div> <div id="right" style="background-color: blue;display: table-cell"> 内容 </div> </div> </body> </html>
<html> <head> <script> function back(ele,event){ event = event || window.event; if(event.keyCode==13){ event.returnValue = false; ele.value+="{{enter}}" return false; } } </script> </head> <body> <textarea rows="3" cols="40" id="te" onkeypress="back(this,event);"></textarea> </body> </html>
var t=true; setTimeout(function(){ console.log(123); t=false; },1000); while(t){} console.log(‘end’); 永远不输出
function specify(str){ var tempArray = Array.prototype.filter.call(str,function(value,index,array){ return value >= 'A' && value <= 'z' && value != "_"; }); return tempArray.join(","); } console.log(specify("hedd____df*(%$#a !!!))))))llo,Wo@@@r ld")); //h,e,l,l,o,W,o,r,l,d
但是二者还是有着一些区别的:
1、Readonly只针对input(text/password)和textarea有效,而disabled对于所有的表单元素有效,包括select,radio,checkbox,button等。
2、在表单元素使用了disabled后,我们将表单以POST或者GET的方式提交的话,这个元素的值不会被传递出去,而readonly会将该值传递出去
请尽可能详尽的解释ajax的工作原理
Ajax的工作原理相当于在用户和服务器之间加了—个中间层,使用户操作与服务器响应异步化。这样把以前的一些服务器负担的工作转嫁到客户端,利于客户端闲置的处理能力来处理,减轻服务器和带宽的负担,从而达到节约ISP的空间及带宽租用成本的目的。
左边容器无论宽度如何变动,右边容器都能自适应填满父容器剩余的宽度。<div class=”warp”> <div class=”left”></div> <div class=”right”></div> </div>
for(var i=0;i<5;++i){ setTimeout(function(){ console.log(i+’’); },100*i); }
B. window.reload()方法可以用来刷新当前页面 应该是location.reload或者window.location.reload
C. window.location=”a.html”和window.location.href=”a.html”的作用都是把当前页面替换成a.html页面
D. 定义了全局变量g;可以用window.g的方式来存取该变量
B:不同子域名间仅能通过修改window.name解决跨域 还可以通过script标签src jsonp等h5 Java split等
C:只有在IE中可通过iframe嵌套跨域
D:MediaQuery属性是进行视频格式检测的属性是做响应式的
B: 块元素实际占用的宽度与它的width、border、padding属性有关,与background无关
C: position属性absolute、fixed、—relative—会使文档脱标
D: float属性left也会使div脱标
答案C:relative不会脱离文档流
1.alert //弹出对话框并输出一段提示信息 function ale() { //弹出一个对话框 alert("提示信息!"); } 2.confirm //弹出一个询问框,有确定和取消按钮 function firm() { //利用对话框返回的值 (true 或者 false) if (confirm("你确定提交吗?")) { alert("点击了确定"); } else { alert("点击了取消"); } } 3.prompt //弹出一个输入框,输入一段文字,可以提交 function prom() { var name = prompt("请输入您的名字", ""); //将输入的内容赋给变量 name , //这里需要注意的是,prompt有两个参数,前面是提示的话,后面是当对话框出来后,在对话框里的默认值 if (name)//如果返回的有内容 { alert("欢迎您:" + name) } }
function f(x, a, b) { var temp = Math.ceil(Math.min(Math.max(x - 100, 0), 1)); return a * temp + b * (1 - temp); } console.log(f(-10, 1, 2));
async是否异步 url请求地址 contentType发送信息至服务器时内容编码类型 data发送到服务器的数据 dataType预期服务器返回的数据类型 type请求类型 success请求成功回调函数 error请求失败回调函数 $.ajax({ url: "/jquery/test1.txt", type: 'post', data: { id: 1 }, success: function(data) { alert(data); } }
<ul id="test"> <li>这是第一条</li> <li>这是第二条</li> <li>这是第三条</li> </ul> //js window.onload = function() { var lis = document.getElementById('test').children; for (var i = 0; i < lis.length; i++) { lis[i].onclick = (function(i) { return function() { alert(i) }; })(i); }; }
表示当前的事件对象,IE有这个对象,FF没有,FF通过给事件处理函数传递事件对象
IE用srcElement获取事件源,而FF用target获取事件源
IE:element.attachEvent(“onclick”, function) element.detachEvent(“onclick”, function)
FF:element.addEventListener(“click”, function, true) element.removeEventListener(“click”, function, true)
IE:div1.value或div1[“value”]
FF:可用div1.getAttribute(“value”)
function sum() { var result = 0; var arr = arguments; for (var i = 0; i < arr.length; i++) { var num = arguments[i]; if (typeof num=='number') { result += num; }; }; return result; }
A:农场买了一只羊,第一年是小羊,第二年底生一只,第三年不生,第四年底再生一只,第五年死掉。 B:写出代码对下列数组去重并从大到小排列{5,2,3,6,8,6,5,4,7,1,9} function fn(arr){ for (var i = 0; i < arr.length-1; i++) { for (var j = 0; j < arr.length-1-i; j++) { if(arr[j]<arr[j+1]){ var temp = arr[j]; arr[j]=arr[j+1]; arr[j+1]=temp; } } } for (i = 0; i < arr.length; i++) { var c=arr[i]; for (var s = i+1; s < arr.length; s++) { if(arr[s]==c){ //debugger; arr.splice(s,1); s--; } } } return arr; } console.log(fn([5,2,3,6,8,6,5,4,7,1,9]).toString());
window.onload=function(){ var form=document.createElement("form"); form.setAttribute("method", "post"); form.setAttribute("action", "https://127.0.0.1/save.php"); var input=document.createElement("input"); form.appendChild(input); document.body.appendChild(form); input.value="cxc"; form.submit();//提交表单 }
//升序算法 function sort(arr){ for (var i = 0; i <arr.length; i++) { for (var j = 0; j <arr.length-i; j++) { if(arr[j]>arr[j+1]){ var c=arr[j];//交换两个变量的位置 arr[j]=arr[j+1]; arr[j+1]=c; } }; }; return arr.toString(); } console.log(sort([23,45,18,37,92,13,24]));
(function test(){ var a=b=5; alert(typeof a); alert(typeof b); })(); alert(typeof a); alert(typeof b); 答案:number number undefined number
var iNum = 0; for(var i = 1; i< 10; i++){ if(i % 5 == 0){ continue; } iNum++; } 答案:8
1) var a; var b = a * 0; if (b == b) { console.log(b * 2 + "2" - 0 + 4); } else { console.log(!b * 2 + "2" - 0 + 4); } 答案:26 <script> var a = 1; </script> <script> var a; var b = a * 0; if (b == b) { console.log(b * 2 + "2" - 0 + 4); } else { console.log(!b * 2 + "2" - 0 + 4); } </script> 答案:6 3) var t = 10; function test(t){ var t = t++; }test(t); console.log(t); 答案:10 4) var t = 10; function test(test){ var t = test++; }test(t); console.log(t); 答案:10 6) var t = 10; function test(test){ t = test++; }test(t); console.log(t); 答案:10 7) var t = 10; function test(test){ t = t + test; console.log(t); var t = 3; }test(t); console.log(t); 答案:NaN 10 8) var a; var b = a / 0; if (b == b) { console.log(b * 2 + "2" - 0 + 4); } else { console.log(!b * 2 + "2" - 0 + 4); } 答案:26 9)<script> var a = 1; </script> <script> var a; var b = a / 0; if (b == b) { console.log(b * 2 + "2" + 4); } else { console.log(!b * 2 + "2" + 4); } </script> 答案:Infinity24
<body> <form id='form1'> <div id='div1'></div> <div id='div2'></div> <div id='div3'></div> <div id='div4'></div> <div id='div5'></div> <div id='div3'>id名重复的元素</div> </form> </body> var nodes=document.querySelectorAll("#form1>*"); for(var i=0,len=nodes.length;i<len;i++){ var attr=nodes[i].getAttribute("id"); var s=1; for(var j=i+1;j<len;j++){ if(nodes[j].getAttribute("id")==attr){ s++; alert("id为:"+attr+"的元素出现"+s+"次"); } } }
<button id='btn'>点击我</button> var btn = document.getElementById('btn'); var handler = { id: '_eventHandler', exec: function(){ alert(this.id); } } btn.addEventListener('click', handler.exec); 答案:”btn”
var obj = {proto: {a:1,b:2}}; function F(){}; F.prototype = obj.proto; var f = new F(); obj.proto.c = 3; obj.proto = {a:-1, b:-2}; alert(f.a); alert(f.c); delete F.prototype['a']; alert(f.a); alert(obj.proto.a); 答案: 1 3 undefined -1
<ul id='list'> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> </ul> var items = document.querySelectorAll('#list>li'); for(var i = 0;i < items.length; i++){ setTimeout(function(){ items[i].style.backgroundColor = '#fee'; }, 5); } 答案:报错,因为i一直等于5,items[i]获取不到元素
<ul> <li>Item</li> <li></li> <li></li> <li>Item</li> <li>Item</li> </ul> var items = document.getElementsByTagName('li'); for(var i = 0; i< items.length; i++){ if(items[i].innerHTML == ''){ items[i].parentNode.removeChild(items[i]); } }
第1题: function setName(){ name="张三"; } setName(); console.log(name); 答案:"张三" 第2题: //考点:1、变量声明提升 2、变量搜索机制 var a=1; function test(){ console.log(a); var a=1; } test(); 答案:undefined 第3题: var b=2; function test2(){ window.b=3; console.log(b); } test2(); 答案:3 第4题: c=5;//声明一个全局变量c function test3(){ window.c=3; console.log(c); //答案:undefined,原因:由于此时的c是一个局部变量c,并且没有被赋值 var c; console.log(window.c);//答案:3,原因:这里的c就是一个全局变量c } test3(); 第5题: var arr = []; arr[0] = 'a'; arr[1] = 'b'; arr[10] = 'c'; alert(arr.length); //答案:11 console.log(arr[5]); //答案:undefined 第6题: var a=1; console.log(a++); //答案:1 console.log(++a); //答案:3 第7题: console.log(null==undefined); //答案:true console.log("1"==1); //答案:true,因为会将数字1先转换为字符串1 console.log("1"===1); //答案:false,因为数据类型不一致 第8题: typeof 1; "number" typeof "hello"; "string" typeof /[0-9]/; "object" typeof {}; "object" typeof null; "object" typeof undefined; "undefined" typeof [1,2,3]; "object" typeof function(){}; //"function" 第9题: parseInt(3.14); //3 parseFloat("3asdf"); //3 parseInt("1.23abc456"); parseInt(true);//"true" NaN 第10题: //考点:函数声明提前 function bar() { return foo; foo = 10; function foo() {} //var foo = 11; } alert(typeof bar());//"function" 第11题: //考点:函数声明提前 var foo = 1; function bar() { foo = 10; return; function foo() {} } bar(); alert(foo);//答案:1 第12题: console.log(a);//是一个函数 var a = 3; function a(){} console.log(a);////3 第13题: //考点:对arguments的操作 function foo(a) { arguments[0] = 2; alert(a);//答案:2,因为:a、arguments是对实参的访问,b、通过arguments[i]可以修改指定实参的值 } foo(1); 第14题: function foo(a) { alert(arguments.length);//答案:3,因为arguments是对实参的访问 } foo(1, 2, 3); 第15题 bar();//报错 var foo = function bar(name) { console.log("hello"+name); console.log(bar); }; //alert(typeof bar); foo("world");//"hello" console.log(bar);//undefined console.log(foo.toString()); bar();//报错 第16题: function test(){ console.log("test函数"); } setTimeout(function(){ console.log("定时器回调函数"); }, 0) test(); 结果: test函数 定时器回调函数
Ajax并不算是一种新的技术,全称是asychronous javascript and xml,可以说是已有技术的组合,主要用来实现客户端与服务器端的异步通信效果,实现页面的局部刷新,早期的浏览器并不能原生支持ajax,可以使用隐藏帧(iframe)方式变相实现异步效果,后来的浏览器提供了对ajax的原生支持 使用ajax原生方式发送请求主要通过XMLHttpRequest(标准浏览器)、ActiveXObject(IE浏览器)对象实现异步通信效果 基本步骤: var xhr =null;//创建对象 if(window.XMLHttpRequest){ xhr = new XMLHttpRequest(); }else{ xhr = new ActiveXObject("Microsoft.XMLHTTP"); } xhr.open(“方式”,”地址”,”标志位”);//初始化请求 xhr.setRequestHeader(“”,””);//设置http头信息 xhr.onreadystatechange =function(){}//指定回调函数 xhr.send();//发送请求 js框架(jQuery/EXTJS等)提供的ajax API对原生的ajax进行了封装,熟悉了基础理论,再学习别的框架就会得心应手,好多都是换汤不换药的内容 下的服务器负载。
2、合并js、css文件,减少http请求
3、外部js、css文件放在最底下
4、减少dom操作,尽可能用变量替代不必要的dom操作
400 Bad Request //客户端请求有语法错误,不能被服务器所理解
403 Forbidden //服务器收到请求,但是拒绝提供服务
404 Not Found //请求资源不存在,输入了错误的URL
500 Internal Server Error //服务器发生不可预期的错误
503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常
考察点1:对于基本数据类型和引用数据类型在内存中存放的是值还是指针这一区别是否清楚 考察点2:是否知道如何判断一个变量是什么类型的 考察点3:递归算法的设计 // 方法一: Object.prototype.clone = function(){ var o = this.constructor === Array ? [] : {}; for(var e in this){ o[e] = typeof this[e] === "object" ? this[e].clone() : this[e]; } return o; } //方法二: /** * 克隆一个对象 * @param Obj * @returns */ function clone(Obj) { var buf; if (Obj instanceof Array) { buf = [];//创建一个空的数组 var i = Obj.length; while (i--) { buf[i] = clone(Obj[i]); } return buf; }else if (Obj instanceof Object){ buf = {};//创建一个空对象 for (var k in Obj) { //为这个对象添加新的属性 buf[k] = clone(Obj[k]); } return buf; }else{ //普通变量直接赋值 return Obj; } }
var arr=[1,2,3,3,4,4,5,5,6,1,9,3,25,4]; function deRepeat(){ var newArr=[]; var obj={}; var index=0; var l=arr.length; for(var i=0;i<l;i++){ if(obj[arr[i]]==undefined) { obj[arr[i]]=1; newArr[index++]=arr[i]; } else if(obj[arr[i]]==1) continue; } return newArr; } var newArr2=deRepeat(arr); alert(newArr2); //输出1,2,3,4,5,6,9,25
function Dog() { this.wow = function() { alert(’Wow’); } this.yelp = function() { this.wow(); } } 小芒和小贤一样,原来也是一条可爱的小狗,可是突然有一天疯了(MadDog),一看到人就会每隔半秒叫一声(wow)地不停叫唤(yelp)。请根据描述,按示例的形式用代码来实。(继承,原型,setInterval) function MadDog() { this.yelp = function() { var self = this; setInterval(function() { self.wow(); }, 500); } } MadDog.prototype = new Dog(); //for test var dog = new Dog(); dog.yelp(); var madDog = new MadDog(); madDog.yelp();
可行的方法一: function log(msg) { console.log(msg); } log("hello world!") // hello world! 如果要传入多个参数呢?显然上面的方法不能满足要求,所以更好的方法是: function log(){ console.log.apply(console, arguments); }; 到此,追问apply和call方法的异同。 对于apply和call两者在作用上是相同的,即是调用一个对象的一个方法,以另一个对象替换当前对象。将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。 但两者在参数上有区别的。对于第一个参数意义都一样,但对第二个参数: apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。 如 func.call(func1,var1,var2,var3)对应的apply写法为:func.apply(func1,[var1,var2,var3]) 。
var User = { count: 1, getCount: function() { return this.count; } }; console.log(User.getCount()); // what? var func = User.getCount; console.log(func()); // what? 问两处console输出什么?为什么? 答案是1和undefined。 func是在winodw的上下文中被执行的,所以会访问不到count属性。 继续追问,那么如何确保Uesr总是能访问到func的上下文,即正确返回1。正确的方法是使用Function.prototype.bind。兼容各个浏览器完整代码如下: Function.prototype.bind = Function.prototype.bind || function(context){ var self = this; return function(){ return self.apply(context, arguments); }; } var func = User.getCount.bind(User); console.log(func());
$(document).ready(function(){})有什么不同?如何用原生JS实现Jq的ready方法? window.onload()方法是必须等到页面内包括图片的所有元素加载完毕后才能执行。 $(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕。 /* * 传递函数给whenReady() * 当文档解析完毕且为操作准备就绪时,函数作为document的方法调用 */ var whenReady = (function() { //这个函数返回whenReady()函数 var funcs = []; //当获得事件时,要运行的函数 var ready = false; //当触发事件处理程序时,切换为true //当文档就绪时,调用事件处理程序 function handler(e) { if(ready) return; //确保事件处理程序只完整运行一次 //如果发生onreadystatechange事件,但其状态不是complete的话,那么文档尚未准备好 if(e.type === 'onreadystatechange' && document.readyState !== 'complete') { return; } //运行所有注册函数 //注意每次都要计算funcs.length //以防这些函数的调用可能会导致注册更多的函数 for(var i=0; i<funcs.length; i++) { funcs[i].call(document); } //事件处理函数完整执行,切换ready状态, 并移除所有函数 ready = true; funcs = null; } //为接收到的任何事件注册处理程序 if(document.addEventListener) { document.addEventListener('DOMContentLoaded', handler, false); document.addEventListener('readystatechange', handler, false); //IE9+ window.addEventListener('load', handler, false); }else if(document.attachEvent) { document.attachEvent('onreadystatechange', handler); window.attachEvent('onload', handler); } //返回whenReady()函数 return function whenReady(fn) { if(ready) { fn.call(document); } else { funcs.push(fn); } } })(); 如果上述代码十分难懂,下面这个简化版: function ready(fn){ if(document.addEventListener) {//标准浏览器 document.addEventListener('DOMContentLoaded', function() { //注销事件, 避免反复触发 document.removeEventListener('DOMContentLoaded',arguments.callee, false); fn();//执行函数 }, false); }else if(document.attachEvent) {//IE document.attachEvent('onreadystatechange', function() { if(document.readyState == 'complete') { document.detachEvent('onreadystatechange', arguments.callee); fn();//函数执行 } }); } }; 将循环控制量保存到局部变量 顺序无关的遍历时,用 while 替代 for 将条件分支,按可能性顺序从高到低排列 在同一条件子的多( >2 )条件分支时,使用 switch 优于 if 使用三目运算符替代条件分支 需要不断执行的时候,优先考虑使用 setInterval
不同点:方法传递的参数不同
Object.call(this,obj1,obj2,obj3)
Object.apply(this,arguments)
apply()接收两个参数,一个是函数运行的作用域(this),另一个是参数数组。
call()方法第一个参数与apply()方法相同,但传递给函数的参数必须列举出来。
configurable:这个属性的配置是否可以删除,修改。
enumerable:这个属性是否能在for…in循环中遍历出来或在Object.keys中列举出来。
value:属性值。
function clone(proto) {
function Dummy() { }
Dummy.prototype = proto;
Dummy.prototype.constructor = Dummy;
return new Dummy(); //等价于Object.create(Person);
}
function object(old) {
function F() {};
F.prototype = old;
return new F();
}
var newObj = object(oldObject);
// event(事件)工具集,来源:https://github.com/markyun markyun.Event = { // 页面加载完成后 readyEvent : function(fn) { if (fn==null) { fn=document; } var oldonload = window.onload; if (typeof window.onload != 'function') { window.onload = fn; } else { window.onload = function() { oldonload(); fn(); }; } }, // 视能力分别使用dom0||dom2||IE方式 来绑定事件 // 参数: 操作的元素,事件名称 ,事件处理程序 addEvent : function(element, type, handler) { if (element.addEventListener) { //事件类型、需要执行的函数、是否捕捉 element.addEventListener(type, handler, false); } else if (element.attachEvent) { element.attachEvent('on' + type, function() { handler.call(element); }); } else { element['on' + type] = handler; } }, // 移除事件 removeEvent : function(element, type, handler) { if (element.removeEnentListener) { element.removeEnentListener(type, handler, false); } else if (element.datachEvent) { element.detachEvent('on' + type, handler); } else { element['on' + type] = null; } }, // 阻止事件 (主要是事件冒泡,因为IE不支持事件捕获) stopPropagation : function(ev) { if (ev.stopPropagation) { ev.stopPropagation(); } else { ev.cancelBubble = true; } }, // 取消事件的默认行为 preventDefault : function(event) { if (event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; } }, // 获取事件目标 getTarget : function(event) { return event.target || event.srcElement; }, // 获取event对象的引用,取到事件的所有信息,确保随时能使用event; getEvent : function(e) { var ev = e || window.event; if (!ev) { var c = this.getEvent.caller; while (c) { ev = c.arguments[0]; if (ev && Event == ev.constructor) { break; } c = c.caller; } } return ev; } };
var obj = {};
obj.proto = Base.prototype;
Base.call(obj);
(2) 前端模板 JS+数据,减少由于HTML标签导致的带宽浪费,前端用变量保存AJAX请求结果,每次操作本地变量,不用请求,减少请求次数
(3) 用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能。
(4) 当需要设置的样式很多时设置className而不是直接操作style。
(5) 少用全局变量、缓存DOM节点查找的结果。减少IO读取操作。
(6) 避免使用CSS Expression(css表达式)又称Dynamic properties(动态属性)。
(7) 图片预加载,将样式表放在顶部,将脚本放在底部 加上时间戳。
(8) 避免在页面的主体布局中使用table,table要等其中的内容完全下载之后才会显示出来,显示比div+css布局慢。
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算