首页 > 技术文章 > JavaScript学习笔记

lovekingly 2015-09-07 16:35 原文

1、数据类型
    5种简单的类型:null undefined boolean string number
    1种复杂的类型:object 包含({}, [])
    代码类型只有一种形式:function
    备注:想了解变量是什么类型可以使用  typeof(变量) 可以方便知晓

    undefined:变量或对象不存在/未定义
    null:变量或对象存在但是值为null  typeof(b) object 但if(b==null){console.log('b is null');}
    booleantrue  false
    number:NAN Infinity是两个特殊之数,NAN是无法用数值表示的数字,而Infinity是代表无穷大的数值
    string:字符串  (字符串是表示文本的最小单位)

    typeof()获取元素类型

2、函数
    function hello(){
        console.log('hello');
    }
    hello();
    function hello(){
        console.log('hello word');
    }
    hello();
    //hello word
    //hello word
    //Javascript并非是按照顺序解释执行而是在解释之前会对JavaScript进行一次预编译以提高执行效率
    //如果是变量的话编译会把所有变量预先定义并且默认值是underfined,而方法则会先编译才会被执行
    //var i=1;时声明了一个window作用域的一个变量;然而写a=1;时声明了一个window属性。
    //变量编译时会预先的定义并默认为underfined 而属性则会按照顺序来解释执行
    
    var hello = function(){
        console.log('hello');
    }
    hello = function(){
        console.log('hello word');
    }
    hello();
    hello();
    //hello word
    //hello word
    备注:为了防止以上情况 我么可以定义两个模块或两个js文件
    <script type="text/javascript">
    function hello(){
        console.log('hello');
    }
    hello();
    </script>

    <script type="text/javascript">
    function hello(){
        console.log('hello word');
    }
    hello();
    </script>

3、作用域
    浏览器宿主中作用域是window。
    var i=1;时声明了一个window作用域的一个变量;然而写a=1;时声明了一个window属性。
    变量在JavaScript预编译时会预先的定义并默认为underfined,而属性则会按照顺序来解释执行。
    
    <script type="text/javascript">
        console.log(a);
        console.log(b);
        var a = "111";
        b = "111";
    </script>
    备注:这里会先输出underfined 然后会报个错提示b is no underfined
          如上代码a是变量、b是属性 所以预编译的时先定义变量默认值underfined而属性则在顺序前面时将提示未定义。

    接下来我们可以谈下函数的作用域问题,每当代码运行进入一个函数时,JavaScript会自动创建一个新的作用域,然后把这个新作用域作为当前域的子作用域,然后把当前的代码作用域切换到这个新的作用域,当代码退出函数时这个新的作用域销毁,把代码交还给他的父作用域。
    <script type="text/javascript">
        var a = 'hello';
        b = 'word';
        test();
        function test(){
            console.log(a +' '+b);
            var a = 'hi';
            b = 'man';
            console.log(a+' '+b);
        }
        console.log(a+' '+b);
    </script>
    如上代码结果:underfined word 、hi man 、 hello man
    备注:为什么开始输出是 underfined word
        代码进入test()方法时将开启一个新的作用域,然后把全局作用域作为他的父作用域。
        test()方法中变量a默认值是underfined而b在test()作用域中没有定义就会去父作用域查找发现是word,如果在执行test()方法前没有b的变量或属性定义那么就会报错了。

    备注:我们在定义变量时候尽量要使用var 虽然JavaScript并不强迫我们这样做。

4、Eval函数
    eval的作用其实很简单,就是把一段字符串传递给js解析器(浏览器)将这段字符串解释成JavaScript代码并执行他。
    <script type="text/javascript">
        eavl('console.log(1)');     //1

        eval('var ii=10;');
        console.log(ii);            //10
    </script>

    eval的作用域
    var test = function(){
        eval('var i=3;');
        console.log(i);
    }
    test();
    console.log(i);
    备注:这里返回3、i is no underfined

    var obj = function(){
        this.a = 1;
        this.b = 2;
        this.c = 3;
        this.funrtn = function(){
            this.d = this.a + this.b;
        }
    }
    var o = new obj();
    o.funrtn();
    console.log(o.d);
    console.log(o.e);//underfined 对象属性不存在时typeof()返回的是underfined

    var obj = {
        a:1,
        b:2,
        c:3,
        funrtn:function(){
            this.d = this.a + this.b;
        }
    };
    obj.g = 20;
    obj.funrtn();
    console.log(obj.d);
    备注:此处不能实例化obj  因为会提示object is not a function 

    var obj = function(){
        this.a = 1;
        this.b = 2;
        this.c = 3;        
    }
    //prototype 原型
    obj.prototype.funrtn = function(){
        this.d = this.a + this.b;
    }
    obj.prototype.g = 20;
    var o = new obj();
    o.funrtn();
    console.log(o.d);

    备注:function(){}方法可以使用prototype来添加属性和方法,
        而object对象不用使用prototype因对象可以直接obj.属性/方法添加

    eval()和with()一起使用的方法
    var funrtn = function(){
        c = a + b;
    }
    var obj = {
        a : 1,
        b : 2,
        c : 5
    };
    with(obj){
        eval('fun='+funrtn);
    }
    fun();
    console.log(obj.c);


5、类和对象
    JavaScript是一种基于prototype的面向对象语言;
    面向对象语言三大特点:继承、多态、封装

    JavaScript可以为对象添加任意属性和方法
    var person = {};
    person.name = 'apple';
    person.age = 20;
    person.showmessage = function(){
        console.log("hi av8d my name is "+person.name+" and "+person.age+" year old");
    }
    person.showmessage();

    var person = {
        name : 'apple',
        age : 20,
        showmessage : function(){
            console.log("hi av8d my name is "+this.name+" and "+this.age+" year old");
        },
    };
    person.showmessage();//方法里面的this也可以换成person类名称

    var obj = function(){
        this.name = 'apple';
        this.age = 20;
        this.funrtn = function(){
            console.log("hi av8d my name is "+this.name+" and "+this.age+" year old");
        }
    }
    var o = new obj();
    o.funrtn();

    var obj = function(name, age){
        this.name = name;
        this.age = age;
        this.funrtn = function(){
            console.log("hi av8d my name is "+this.name+" and "+this.age+" year old");
        }
    }
    var o = new obj('baba', 30);
    o.funrtn();
    //console.log(o); o.name 或 o['name']都是可以的

6、原型链的原理 prototype 和 __proto__
    说道prototype不得不说下new的过程
    var person = function(){};
    var p = new person();

    a、var p = {};//初始化一个对象p
    b、p.__proto__ = person.prototype;
    c、person.call(p);//这里构造了p  有关call的用法以后再看
    备注:关键是第2步,每一个对象都会在内部初始化一个属性__proto__,如果对象内部不存在某个属性时会去__proto__里找这个属性,这就是我们常说的原型链的概念。
    例如:
    var obj = function(){};
    var o = new obj();
    console.log(o.__proto__===obj.prototype);//这里代码返回的是true

    概念清楚了,来看下如下代码:
    var person = function(){};
    person.prototype.say = function(){
        console.log('person say');
    }
    var p = new person();
    p.say(); //person say

    备注:p实例化之后p.say()执行之前修改person.prototype.say的输出
    var p = new person();
    person.prototype.say = function(){
        console.log('person say again');
    }
    p.say(); //person say again 
    这里为什么呢?因为p.say()调用时候会去查看原型链中的say方法
    首先var p=new Person();可以得出p.__proto__=Person.prototype。
    那么当我们调用p.Say()时首先p中没有Say这个属性于是他就需要到他的__proto__中去找
    也就是prson.prototype而我们在上面定义了person.prototype.Say=function(){};
    于是就找到了这个方法。

7、用JSON做原型
    在js类和对象中我们还可以使用json设置一个对象。
    var person = {
        name : 'apple',
        age : 20,
        say : function(){
            console.log("hi my name is "+this.name+" "+this.age+" year old");
        }
    };
    person.say();
    备注:这个对象是不能重用的,那么我们如何把对象作为原型的呢?
    因为在一个json对象中有一个构造方法是不可能的,那么我们可以做一个简单的方式
    var person = {
        create : function(name, age){
            this.name = name;
            this.age = age;
        },
        say : function(){
            console.log("hi my name is "+this.name+" "+this.age+" year old");
        }
    };
    person.create('apple', 30);
    person.say();
    但是通过这个方法我们还是无法使用person作为原型;如果person.prototype.say = function(){}就可以解决这个问题;于是乎:
    var person = {
        create : function(name, age){
            this.name = name;
            this.age = age;
        },
        say : function(){
            console.log("hi my name is "+this.name+" "+this.age+" year old");
        }
    };
    var x = function(){};
    x.prototype = person;
    var p = new x();
    p.create('aaaaaaaa', 36);
    p.say();

8、prototype封装
    var person = function(name, age){
        this.name = name;
        this.age = age;
    }
    person.prototype.say = function(){
        console.log("my name is "+this.name+" "+this.age+" year old");
    }
    var p = function(name, age, salary){
        this.salary = salary;
        person.call(this, name, age);
    }
    p.prototype = new person();//这里是把person加到原型链上
    var o = new p('apple', 22, 4000);
    o.say();

9、网页运行原理
    当我们打开一个网页时浏览器会首先创建一个窗口window对象,为了加载网页文档window对象有创建一个document对象,然后把打开的网页加载到document下,网页就是这样的加载过程;页面一边加载一边呈现所以我们网速慢的时候可以看到页面从上到下一点点的打开;
    当我们用<script src=''>引用其他js时浏览器会派遣其他线程去下载,当页面加载都结束后浏览器会触发window或body对象的onload()事件
    
10、Ajax 
    Asynchronous JavaScript And Xml异步JavaScript和XML

 

推荐阅读