Javascript学习笔记一:基础

        概述

        javascript是一个神奇语言,简单易学,特别是近些年nodejs服务端js的崛起,再加上reactjs,angualrjs等等,可以说现在js是做火的一种语言。程序员很实在,够用就好,我们用大量的js超集,js库,可以说人人都会js,但几乎是很少会花大量时间学习javascript,遇到坑,经常会不知其所以然。一大堆时髦的各种js经常挂嘴边,各种吹水。经常用的的是jquery。基本上就没从头好好看过javascript。所以这就是我的新的学习目标,从头好好理一理下javascript。

       虽然开头的比较基础的,大家都会,但我觉得好好静下心来学习最基础的东西,未尝不会没有收获。

         准备工作

          js目前最新标准是ecmascript6,简称es6,所有浏览器都在像es6标准靠拢,我们测试运行javascript可以用身边随便哪个最新版的浏览器,

 如果是chrome,按alt+command+I   (windows下是ctrl+shift+I) 弹出开发者工具,选择console选项页,就可以输入js,换行按shift+回车换行

 如果安装了node.js的同学也可以直接用 node.js命令行执行js (注意,某些方法,比如alert,prompt 这些是浏览器的方法,node.js是不会执行的)

        输入输出

为方便代码编写,我们定义下常用的输入输出,输出主要用console.log(),输入用prompt,类似下图

       

        类型替换

         javascript类型可以随意替换,见下图,两个输入颜色不一样

        

       相同判断

       对于“123”以及123,是否相同,当字符串和数字比较的时候,js会自动把字符串“123”转为数字123,然后再对比123==123,那当然相同了,

        但这样很容易出错,所以如果js要判断完全相同的话用3个等号见下

       

        备注       

        良好的代码必须要有很漂亮的备注说明,与大多数语言一样,单行备注用//,多行备注用/*   */, 

        我觉得好的备注应该要解析为什么这么做,而不是解析如何去做

        

var a = 24;     // 24 代表着活着的意义


/* 为什么是24呢,
   我随便写的一个数字,
   没意义啦 */
var a = 24;
          变量

         变量用var定义,在js中变量类型会隐性转换 ,如下图,数字和字符串相加的时候会自动转为字符串,相乘的时候字符串又回自动转为数字,如果需要指定格式,则可以用显性转换,比如下图的Number,显性将字符串专为数字。     

var xa=2;
var xb='3';
console.log(xa+xb);
console.log(xa+Number(xb));
console.log(xa*xb);
 23
 5
 6

        常量

        在es6规范中新增了常量的定义,使用const定义常量,常量不可更改,常量名建议以全大写名来定义,词组之间用下划线隔开

   

const TAX_RATE=0.17;
var price=100;
console.log((price*TAX_RATE).toFixed(2));
17.00

         块

        块以大括号对{。。。}隔开,左大括号在js里建议不要分行,同行里显示。类似下图,不要用大括号单独为一行

if (amount > 10) {          // <-- block attached to `if`
    amount = amount * 2;
    console.log( amount );  // 199.98
}
        条件

        和大多数语言一样,条件就是if (){} else {}这种格式,

        注意:在js中条件中的值为bool类型,如果条件的值不是bool类型,会隐性转换为truthy/falsy,在js中,除了null,undefined,0,-0,NaN 和''会转为falsy,其他的都会转为truthy,字符串'0'也会转换为truthy

       

const ACCESSORY_PRICE = 9.99;
var bank_balance = 302.13;
var amount = 99.99;
amount = amount * 2;
// 钱还够不够呀
if ( amount < bank_balance ) {
    console.log( "买买买" );
    amount = amount + ACCESSORY_PRICE;
}
// 没钱
else {
    console.log( "看看就好" );
}

         还有一种条件就是switch(){case :;}

switch (a) {
    case 2:
    case 10:
        // some cool stuff
        break;
    case 42:
        // other stuff
        break;
    default:
        // fallback
}
       还有就是三元运算符 ?:类似下图

  

var b = (a > 41) ? "hello" : "world";



         循环

         循环可以用while(){}   ,或者do{} while() ,区别就是第一次要不要做判断。还有一种就是for (var i=0;i<10;i++) for循环,跟其他语言一样

         函数

         函数以function 标注,类似下行代码, function 带函数名,括号中带参数,后面通过函数名调用

function printAmount(amt) {
    console.log( amt.toFixed( 2 ) );
}

var amount = 99.99;

printAmount( amount * 2 );
          作用域

         作用域就是语法的有效范围,js中每个函数都是自己独立的作用域,在独立的作用域中定义的变量只有该域以及子域才能访问,。如下代码所示,

        

function one() {
    // 这个a只存在于one函数
    var a = 1;
    console.log( a );
}

function two() {
    // 这个a只存在于two函数
    var a = 2;
    console.log( a );
}

one();      // 1
two(); 
function foo() {
    var a = 1;

    if (a >= 1) {
        let b = 2;

        while (b < 5) {
            let c = b * 2;
            b++;

            console.log( a + c );
        }
    }
}

foo();
// 5 7 9

         类型

        js现有的类型有以下几种:,通过typeof 运算符可以得出变量的类型,注意,typeof 返回的是一串字符串。如果是函数的话,typeof 会返回"function"

       

string    // 字符串
number    // 字符串 
boolean   // true false 布尔类型
null and undefined // 空值
object    // 对象基类
symbol    // es6中新增的标注

        

var a;
typeof a;               // "undefined"

a = "hello world";
typeof a;               // "string"

a = 42;
typeof a;               // "number"

a = true;
typeof a;               // "boolean"

a = null;
typeof a;               // "object" -- 这个明显是bug

a = undefined;
typeof a;               // "undefined"

a = { b: "c" };
typeof(a);               // "object"
          Objects数据

           js 的object其实就是键值对,用{}包括,以:隔开键值,

     

var obj = {
    a: "hello world",
    b: 42,
    c: true
};

obj.a;      // "hello world"
obj.b;      // 42
obj.c;      // true

obj["a"];   // "hello world"
obj["b"];   // 42
obj["c"];   // true

          Array数组

          array数组,用[]包括,这些规则其实跟json是一样的。

var arr = [
    "hello world",
    42,
    true
];

arr[0];         // "hello world"
arr[1];         // 42
arr[2];         // true
arr.length;     // 3

typeof arr;     // "object"
         Functions函数对象

          上段已经简要讲过了function,function本身就是object的子类,所以function可以new,并且可以设置属性

function foo() {
    return 42;
}

foo.bar = "hello world";

typeof foo;         // "function"
typeof foo();       // "number"
typeof foo.bar;     // "string"
         js函数有点特别之处,就是定义的函数,函数名本身也视为一个变量,也就是说他可以把函数名作为值赋值给其他变量

var foo = function() {
    // 匿名函数
};

var x = function bar(){
    // bar是函数名,同时作为值赋值给x
};

   

        自带方法

        js中有自带一些方法,如下,调用这些方法的时候,

       比如调用a.toUpperCase, a会封装成string类型的object对象,然后调用string对象的toUpperCase()方法,

       调用b.toFixed(4)的时候,b会封装成number类型的object对象,然后调用number对象的toFixed()方法

var a = "hello world";
var b = 3.14159;

a.length;               // 11
a.toUpperCase();        // "HELLO WORLD"
b.toFixed(4);           // "3.1416"
          转换

          转换分2种,一种隐性转换,一种显性转换,显性转换就是用函数强制转换,隐性则是在运算的时候自动转换。

var a = "42";

var b = Number( a );  //显性转换

a;              // "42"
b;              // 42 -- the number!
var a = "42";

var b = a * 1;  // 这里 "42" 隐性转换为 42 

a;              // "42"
b;              // 42 -- the number!
          逻辑运算

          == (数值相同)  ===(数值相同并且类型相同)      !=(数值不相同)  !==(数值不同或者类型不同)

         >(大于符号,不只数字可以判断,字符串也可以做大小判断,以ascii数字排序为依据,比如  'b'>'a' , 'a'>'B'

         < (小于符号,与>相反)

       注意:

        如果类型相同,则直接比较,如果不同,则会做转换

       如果一方是bool类型,则bool类型会先隐性转为Number   //true 为1,false为0

       如果字符和数字做比较,则字符会转换为Number ,如果转换失败,则值为NaN,NaN跟任何类型对比都是false

       如果是object,则先取getValue ,如果没有值,则取toString,如果都取不到,就是个独立的object

      比如[]  与[] 是不同的, []==[] []>[]   []<[] 都是false 

       null==undefined

        undefined 除了与null比较是true,与任何数据做比较,不管>,< == 都是false,类似NaN

       null与数据对比时,可以看成是0与数字对比,但0==null 为false

       

       

       比如42>‘foo’, 就会 先把'foo'转换为number,然后得到invalid number NaN

        


var a = 41;
var b = "42";
var c = "43";

a < b;      // true
b < c;      // true
var a = 42;
var b = "foo";

a < b;      // false
a > b;      // false
a == b;     // false
        

           Strict Mode 严格模式

           Strict Mode是es5新加的模式,添加“use strict"来表明js必须遵守新的es5以上的规范,如下,限定use strict 之后,变量名必须提前定义,否则的话就会报错, 

       

function foo() {
    "use strict";   // turn on strict mode
    a = 1;          // `var` missing, ReferenceError
}

foo();

          javascript编码要尽量使用"use strict",养成良好的js编码规范。

          立即执行函数

          立即执行函数就是马上执行,而不要调用的函数,如下,(function fName(){...})(); 用括号把函数括起来,并带()执行,

var a = 42;

(function IIFE(){
    var a = 10;
    console.log( a );   // 10
})();

console.log( a );       // 42
       这个主要作用在于保护变量,因为javascript中没用私有作用域的概念,如果在多人开发的项目上,你在全局或局部作用域中声明了一些变量,可能会被其他人不小心用同名的变量给覆盖掉,根据javascript函数作用域链的特性,可以使用这种技术可以模仿一个私有作用域,用匿名函数作为一个“容器”,“容器”内部可以访问外部的变量,而外部环境不能访问“容器”内部的变量,所以( function(){…} )()内部定义的变量不会和外部的变量发生冲突,俗称“匿名包裹器”或“命名空间”

       Closure闭包

        闭包是js中非常非常重要的一个技能,但很少人花时间去关注,大概讲解一下,闭包简单讲就是记住函数(包括函数作用域中的变量),即使函数已经结束,回调该函数的时候,记住函数(同样包括该作用域中的变量)

   

function makeAdder(x) {
    // 参数 `x` 作为内部变量

    // 内部函数 `add()` 使用 `x`, 所以
    // 就存在一个闭包
    function add(y) {
        return y + x;
    };

    return add;
}
        我们来调用一个makeAdder

//  plus one `plusTen` 定义为对`add(..)`函数的引用,有一个来自于makeAdderx参数的闭包
var plusOne = makeAdder( 1 );

var plusTen = makeAdder( 10 );

plusOne( 3 );       // 4  <-- 1 + 3
plusOne( 41 );      // 42 <-- 1 + 41

plusTen( 13 );      // 23 <-- 10 + 13

       moudle模块模式

        closure闭包最常见于moudle模块,函数本身是有私有域,要访问函数内部方法,变量就可以用模块模式  举例见下

        

function User(){
    var username, password;

    function doLogin(user,pw) {
        username = user;
        password = pw;

        // do the rest of the login work
    }

    var publicAPI = {
        login: doLogin
    };

    return publicAPI;
}

// create a `User` module instance
var fred = User();

fred.login( "fred", "12Battery34!" );

     var fred=User(); 这里没必要加new ,因为User本身是个函数,并不像个class需要实例化,不用new可以节省系统开销。

     每个User() 都是独立的,多个user()之间变量互相不相干

     dologin 函数有包涵username,password的闭包,所以user()执行结束后,还可以通过publicApi来访问username,password

    这里调用login就实现了调用dologin相同的效果。

    

     this标识符

      this是经常用的标识,但却很容易让人搞糊涂。     this在函数中调用,那么指的就是调用方,举例见下

function foo() {
    console.log( this.bar );
}

var bar = "global";

var obj1 = {
    bar: "obj1",
    foo: foo
};

var obj2 = {
    bar: "obj2"
};

// --------

foo();              // "global"
obj1.foo();         // "obj1"
foo.call( obj2 );   // "obj2"
new foo();          // undefined

  注意:如果是strict mode,上面foo()会报错,其他3个调用的确正常,因为严格模式下不允许直接这么访问全局变量bar

    Prototype原型

    原型就是我们调用一个object的属性,如果属性不存在,那么就会查找内部的原型引用找到该属性值

var foo = {
    a: 42
};

// create `bar` and link it to `foo`
var bar = Object.create( foo );

bar.b = "hello world";

bar.b;      // "hello world"
bar.a;      // 42 <-- delegated to `foo`


  bar本身不存在属性a,但因为bar的原型来自foo,js会自动跳到foo,来查找a值,其实是不是感觉有点像继承呢,   

     新旧标准javascript兼容

     ecma script 去前是es6版,但后续都是以年来定义,今年es2016,后面es2017,es2018,每年都有新的语法出现,但主流的浏览器都没法完全支持这些新语法,怎么办呢

难道我们用新js一定要等很多年,等到支持了,再用新的js标准吗,不用担心,有2种技术可以让你的新js用在旧浏览器上

    Polyfilling 

    Polyfill就是让新版js 函数可以运行在旧的浏览器上,举个例子,es6中作废 isNaN  用Number.isNaN,那么我们用Number.isNaN的时候,怎么polyfill让旧版本支持新特性呢,这个就简单了,直接增加以下方法就可以了

if (!Number.isNaN) {
    Number.isNaN = function isNaN(x) {
        return x !== x;
    };
}
 当然,其实我们没必要造轮子,现在已经有现成写好的shim js,直接下载下来即可,调用地址: https://github.com/es-shims/es5-shimhttps://github.com/es-shims/es6-shim

    Transpilling

     Polyfill可以解决新版函数在旧浏览器运行的问题,但无法解决新的语法在旧浏览器会报错的问题,那么还有一个好的办法,就是把新版的js转换成旧版的js,这个过程就叫Transpilling,就是说你写的是新标准的js,其实运行的是旧标准的js,那么为什么不直接用旧标准的写呢,还要转换。用新版写的好处在于

       1:用新的js写代码更易读,更容易维护

      2:浏览器发展很快,js标准现在也是发展越来越快,现在新版不久就会变成标准。作为程序员,你需要掌握这些新家伙。

     举个例子,函数参数默认值是es6中才有的,旧版不支持

function foo(a = 2) {
    console.log( a );
}

foo();      // 2
foo( 42 );  // 42

function foo() {
    var a = arguments[0] !== (void 0) ? arguments[0] : 2;
    console.log( a );
}

     一些转换工具:Babel (https://babeljs.io),Traceur (https://github.com/google/traceur-compiler)

    Non-javascript

     现实中,js就是用在浏览器上,如果说其实我们常写的语句,就不是javascript,你可能会奇怪,最常见的就是Dom api,例如

var el = document.getElementById( "foo" );
     当你在浏览器中运行的时候, document 是个全局变量,实际上它并不是js引擎提供的变量。看上去是js object,实际上是浏览器一个特殊的object,称之为host object

     getElementById看上去是函数,其实是一个接口,用于控制浏览器的dom元素

     类似的还有alert ,console.log()  ,这些都并不是javascript自带的


     尾声

     大致记录了下javascript,其实现在es标准发展太快了,很多知识都在更新,对我来说,记录一遍,还是很有收获。希望读者你也能有一点点收获。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值