淘先锋技术网

首页 1 2 3 4 5 6 7

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");