1.使用数组的length
length=0清空数组(arr=[]效率更高)
var arr1 = arr2 = [1,2,3];
arr1.length = 0;
console.log(arr2);[]
arr1.length = 1;
console.log(arr2);//[undefined]
缩减数组
var arr = [1,2,3,4,5,6,7,8,9,10];
arr.length = 5;//截取前5个
console.log(arr);//[1,2,3,4,5]
2.push()合并数组
var arr1 = [1,2,3];
var arr2 = [4,5,6];
//谷歌浏览器运行较快
var arr3 = arr1.concat(arr2);//[1,2,3,4,5,6]
//火狐浏览器运行较快
Array.protytype.push.apply(arr1,arr2);//[1,2,3,4,5,6]
Array.prototype.push.apply(arr3,[...arr2,...arr3]);//[4,5,6]因为...arr2的结果为{0:1,1:2,2:3},...arr3的结果为{0:4,1:5,2:6}
3.特性检测
var obj = document.getElementById("box");
//如果使用obj.addEventListener则会给obj添加一个addEventListener属性,为undefined,给对象绑定了很多无用的属性,JS执行效率底下
if("addEventListener" in window){
obj.addEventListener("click",function(){},false)
}else{
obj.attachEvent("onclick",function(){})
}
4.检测一个对象是不是数组
//JavaScript中typeof可以用来检查变量类型,返回:number,boolean,string,object,function和undefined,并没有array,typeof Array为 object
//使用Array.isArray(obj)来判断
var arr = [];
Object.prototype.toString.call(arr)=="[object Array]";
5.数组去重
var arr = [1,1,2,"2",3,4,5,6,6,7,8,9,0,"a","a","b"];
//1.双循环,判断新数组和给定的数组
//2.对象去重法
Array.prototype.unique = function(){
var obj ={};
var newArr = [];
//优化:数组从大到小
// for(var i = this.length-1;i>=0;i--){
for(var i = 0;i<this.length;i++){
//将数组的值放到对象中,利用对象属性的唯一性去重
// obj[this[i]] = "";
//改进:去掉
if(obj[this[i]]== undefined){
obj[this[i]] = ""
//保证数据类型不变,但是字符串类型的"数字"和真正的数字无法区分
newArr.push(this[i])
obj[this[i]] = this[i]
newArr.push(this[i]);
}
if(obj[this[i]]== undefined || obj[this[i]] !==this[i]){
// obj[this[i]] = ""
//保证数据类型不变,但是字符串类型的"数字"和真正的数字无法区分
// newArr.push(this[i])
obj[this[i]] = this[i]
newArr.push(this[i]);
}
}
//改进:去掉
for(var item in obj){
newArr.push(item)
}
}
//改进版
Array.prototype.unique = function(){
var obj = {},newArr = [],i = arr.length;
while(--i>0){
(obj[this[i]] == undefined||obj[this[i]]!==this[i])&&(obj[this[i]]=this[i],newArr.push(this[i]))
return newArr.reverse();
}
}
//3.正则法
Array.prototype.unique = function(){
return this.join(",").match(/([^,]+)(?!.*\1)/ig)
}
arr.unique();
//4.set
var set = new Set([1,1,2,"2",3,4,5,6,6,7,8,9,0,"a","a","b"]);
console.log([...set]);//[1, 2, "2", 3, 4, 5, 6, 7, 8, 9, 0, "a", "b"]
6.全局作用域(Global Scope)
//全局变量 全局作用域
var name = "前端网";
//全局函数 全局作用域
var w3cfuns = function(){
//函数作用域 local Scope
var website = "www.w3cfuns.com";
function getName(){
console.log(name);
}
console.log(website);
}
var sayHi = function(){
// 隐式全局变量 未使用var定义的变量
lang = "Hello.";
console.log(lang);
}
sayHi();
console.log(lang);//"Hello."
//面试题
var test = function(){
if(1+1==2){
var str = "abcd";
}
// js中没有块级作用域,所以str可以被函数内的任意位置调用
alert(str);//输出:"abcd"
}
test();
//java
public static void test(){
if(1+1==2){
String str = "Java中有块级作用域"
}
// 这里拿不到str
}
7.作用域链
在JavaScript中,函数也是对象,实际上,JavaScript里面的一切都是对象,函数对象和其他对象一样,拥有可以通过代码访问的属性和一系列仅供JavaScript引擎访问的内部属性,其中一个内部属性是 Scope,该内部属性包含了函数被创建的【作用域中对象的集合】,这个集合被称为函数的作用域链,它决定了哪些数据能被函数访问。
一个对象的作用域和其定义的位置有关,如果在当前作用域中找不到,则会继续向上级作用域查找,找到则使用,未找到则继续向上找,直到最顶层还没找到,则返回undefined
8.this
<script>
var xiaoming = {
name:"小明",
school:"在美国某大学",
ename:"乔治",
dosomething:"回国",
say:function(){
// this代指当前对象:xiaoming
console.log(this.name+this.school+"他的英文名叫"+this.ename+"他明天就要"+this.dosomething)
},
say2:function(){
// xiaoming当前对象
console.log(xiaoming.name+xiaoming.school+"他的英文名叫"+xiaoming.ename+"他明天就要"+xiaoming.dosomething)
}
}
xiaoming.say();//小明在美国某大学,他的英文名叫乔治,他明天就要回国
// 当我们不知道一个对象叫什么,或者这个对象没有名字但又想调用它的时候,就会使用到this对象
</script>
当我们不知道一个对象叫什么,或者这个对象没有名字但又想调用它的时候,就会使用到this对象
全局作用域中的this
当一段代码在浏览器中执行时,所有的全局变量和对象都是在window对象上定义的,即所有的全局变量和对象都属于window对象
var test = function(){
this.x = 1;
alert(this.x);//1
}
test();
//改造
console.log(window.x);// 1!!!!!!!!!!!
var y = "b";
function test1(){
console.log(this.y);//"b"
// 注意因为上一个函数运行后,给window对象添加了一个属性x,故这里是可以拿到的
console.log(this.x);
}
test1();
//函数自调用中的this也是window!!!
(function(){
console.log(this);//window
})()
// 面试题
var x = 1;
function test3(){
this.x = 100;
}
test3();//this指向window
//输出结果为100
alert(x);
var name = "小明";
var job = "电焊工";
function say(){
alert(this.name+"是一名"+this.job);
}
var it = {
name:"tom",
job:"it",
say:function(){
// 切记,若没有上面两个属性,返回的是undefined是一名undefined,而非小明是一名电焊工,这与作用域链没有关系,而与原型链有关系
alert(this.name+"是一名"+this.job);
}
}
//小明是一名电焊工
say();
this.say();
window.say();
//tom是it
it.say();
window.it.say();
this.it.say();
this公理
this关键字永远都指向函数(方法)的所有者
函数被赋值给变量的this
var it = {
info:["腾讯","阿里巴巴","京东","新浪"],
getInfo:function(){
alert(this.info.join(","));
}
}
//"腾讯,阿里巴巴,京东,新浪"
it.getInfo();
// 相当于把data = function(){alert(this.info.join(","));}
var data = it.getInfo;
//报错 window.info.join(",")
data();
作为对象方法的调用时的this问题
var test = function({
alert(this.x);
})
var o = {}
o.x = 1;
//相当于:o.t = function({
// alert(this.x);
// })
o.t = test;
//输出 1 !!!!!!
o.t();
作为构造函数的调用时的this问题
function test(){
this.x = 1;
}
var o = new test();
//1
alert(o.x);
//undefined
var t = test();
alert(t.x);
解决闭包中的this指向问题
闭包中的this指向为window
var it = {
info:["腾讯","阿里巴巴","京东","新浪"],
getInfo:function(){
console.log(this);
console.log(this.info);
//var that = this
//闭包
function abc(){
// 此时的this为window 输出undefined
console.log(this);//可以改为it\that
console.log(this.info);//可以改为it.info\that.info
}
abc();
}
}
it.getInfo();
//{info: Array(4), getInfo: ƒ}
//["腾讯", "阿里巴巴", "京东", "新浪"]
//Window
//undefined
当this遇到一些特殊的函数时的问题
call、apply用在函数上,JavaScript版本中,原生实现bind,目前IE9+,FF4,Chrome7+,opera
function test1(){
alert("test1");
}
function test2(){
alert("test2");
}
// test1中的this指向test2
test1.call(test2);//test1
var Dog = function(){
this.name = "汪星人";
this.shout = function(){
alert(this.name);
}
}
var Cat = function(){
this.name = "喵星人";
//this.shout = function(){
// alert(this.name);
//}
}
var dog = new Dog();
var cat = new Cat();
dog.shout();
//cat.shout();
//dog.shout中的this指向cat对象
Dog.prototype.shout.call(cat)
call和apply的区别
function myJob(gender,age,company){
alert(this.name+gender+",今年"+age+"岁,是一名"+this.job);
}
var xh = {
name:"小红",
job:"js"
}
// call的传参使用 参数依次传入
myJob.call(xh,"女",20,"alibaba");
// apply的传参使用 参数为数组
myJob.apply(xh,["女",20,"alibaba"]);
// bind的传参使用 参数依次传入
myJob.apply(xh,"女",20,"alibaba");