美文网首页
Javascript学习笔记

Javascript学习笔记

作者: 东东学习室 | 来源:发表于2018-07-03 14:42 被阅读0次

    javascript学习资源
    https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript
    1、数字
    JavaScript 不区分整数值和浮点数值,所有数字在 JavaScript 中均用浮点数值表示,所以在进行数字运算的时候要特别注意。

    0.1 + 0.2 = 0.30000000000000004

    parseInt()parseFloat() 函数会尝试逐个解析字符串中的字符,直到遇上一个无法被解析成数字的字符,然后返回该字符前所有数字字符组成的数字。使用运算符 "+" 将字符串转换成数字,只要字符串中含有无法被解析成数字的字符,该字符串都将被转换成 NaN。请你用这两种方法分别解析“10.2abc”这一字符串,比较得到的结果,理解这两种方法的区别。

    parseFloat("10.2abc")=10.2
    parseInt("10.2abc")=10

    2、字符串

    "hello".length; // 5
    "hello".charAt(0); // "h"
    "hello, world".replace("hello", "goodbye"); // "goodbye, world"
    "hello".toUpperCase(); // "HELLO"

    3、其他类型
    JavaScript 中 nullundefined 是不同的,前者表示一个空值(non-value),必须使用null关键字才能访问,后者是“undefined(未定义)”类型的对象,表示一个未初始化的值,也就是还没有被分配的值。我们之后再具体讨论变量,但有一点可以先简单说明一下,JavaScript 允许声明变量但不对其赋值,一个未被赋值的变量就是 undefined 类型。还有一点需要说明的是,undefined 实际上是一个不允许修改的常量。

    JavaScript 包含布尔类型,这个类型的变量有两个可能的值,分别是 truefalse(两者都是关键字)。根据具体需要,JavaScript 按照如下规则将变量转换成布尔类型:

    1. false0、空字符串("")、NaNnullundefined 被转换为 false
    2. 所有其他值被转换为 true

    4、控制结构
    && 和 || 运算符使用短路逻辑(short-circuit logic),是否会执行第二个语句(操作数)取决于第一个操作数的结果。在需要访问某个对象的属性时,使用这个特性可以事先检测该对象是否为空:

    var name = o && o.getName();
    o=true就继续执行 第二个条件

    或运算可以用来设置默认值:

    var name = otherName || "default";
    otherName =true就取otherName,不再执行第二个条件,否则就取default

    5、对象
    有两种简单方法可以创建一个空对象:

    var obj = new Object();

    var obj = {};

    6、数组
    JavaScript 中的数组是一种特殊的对象。它的工作原理与普通对象类似(以数字为属性名,但只能通过[] 来访问),但数组还有一个特殊的属性——length(长度)属性。这个属性的值通常比数组最大索引大 1。
    创建数组的传统方法是:

    var a = new Array();
    a[0] = "dog";
    a[1] = "cat";
    a[2] = "hen";
    a.length; // 3

    使用数组字面量(array literal)法更加方便

    var a = ["dog", "cat", "hen"];
    a.length; // 3

    注意,Array.length 并不总是等于数组中元素的个数,如下所示:

    var a = ["dog", "cat", "hen"];
    a[100] = "fox";
    a.length; // 101
    记住:数组的长度是比数组最大索引值多一的数。

    可以通过如下方式遍历一个数组

    for (var i = 0; i < a.length; i++) {
    // Do something with a[i]
    }

    遍历数组的另一种方法是使用 for...in 循环。注意,如果有人向 Array.prototype 添加了新的属性,使用这样的循环这些属性也同样会被遍历。所以并不推荐这种方法:

    for (var i in a) {
    // Do something with a[i]
    }

    ECMAScript 5 增加了遍历数组的另一个方法 forEach()

    ["dog", "cat", "hen"].forEach(function(currentValue, index, array) {
    // Do something with currentValue or array[index]
    });

    如果想在数组后追加元素,只需要:

    a.push(item);

    Array(数组)类自带了许多方法

    image.png

    7、函数
    最简单的函数就像下面这个这么简单:

    function add(x, y) {
        var total = x + y;
        return total;
    }
    

    JavaScript 允许你创建匿名函数:

    var avg = function() {
        var sum = 0;
        for (var i = 0, j = arguments.length; i < j; i++) {
            sum += arguments[i];
        }
        return sum / arguments.length;
    };
    

    8、 自定义对象
    构造一个对象:

    function makePerson(first, last) {
        return {
            first: first,
            last: last
        }
    }
    function personFullName(person) {
        return person.first + ' ' + person.last;
    }
    function personFullNameReversed(person) {
        return person.last + ', ' + person.first
    }
    s = makePerson("Simon", "Willison");
    personFullName(s); // Simon Willison
    personFullNameReversed(s); // Willison, Simon
    

    上面的写法虽然可以满足要求,但是看起来很麻烦,因为需要在全局命名空间中写很多函数。既然函数本身就是对象,如果需要使一个函数隶属于一个对象,那么不难得到:

    function makePerson(first, last) {
        return {
            first: first,
            last: last,
            fullName: function() {
                return this.first + ' ' + this.last;
            },
            fullNameReversed: function() {
                return this.last + ', ' + this.first;
            }
        }
    }
    s = makePerson("Simon", "Willison");
    s.fullName(); // Simon Willison
    s.fullNameReversed(); // Willison, Simon
    

    上面的代码里有一些我们之前没有见过的东西:关键字 this。当使用在函数中时,this 指代当前的对象,也就是调用了函数的对象。如果在一个对象上使用点或者方括号来访问属性或方法,这个对象就成了 this。如果并没有使用“点”运算符调用某个对象,那么 this 将指向全局对象(global object)。这是一个经常出错的地方。例如:

    s = makePerson("Simon", "Willison");
    var fullName = s.fullName;
    fullName(); // undefined undefined
    

    当我们调用 fullName() 时,this 实际上是指向全局对象的,并没有名为 first 或 last 的全局变量,所以它们两个的返回值都会是 undefined。

    下面使用关键字 this 改进已有的 makePerson函数:

    function Person(first, last) {
        this.first = first;
        this.last = last;
        this.fullName = function() {
            return this.first + ' ' + this.last;
        }
        this.fullNameReversed = function() {
            return this.last + ', ' + this.first;
        }
    }
    var s = new Person("Simon", "Willison");
    

    我们引入了另外一个关键字:new,它和 this 密切相关。它的作用是创建一个崭新的空对象,然后使用指向那个对象的 this 调用特定的函数。注意,含有 this 的特定函数不会返回任何值,只会修改 this 对象本身。new 关键字将生成的 this 对象返回给调用方,而被 new 调用的函数成为构造函数。习惯的做法是将这些函数的首字母大写,这样用 new 调用他们的时候就容易识别了。

    不过这个改进的函数还是和上一个例子一样,单独调用fullName() 时会产生相同的问题。

    我们的 Person 对象现在已经相当完善了,但还有一些不太好的地方。每次我们创建一个 Person 对象的时候,我们都在其中创建了两个新的函数对象——如果这个代码可以共享不是更好吗?

    function personFullName() {
        return this.first + ' ' + this.last;
    }
    function personFullNameReversed() {
        return this.last + ', ' + this.first;
    }
    function Person(first, last) {
        this.first = first;
        this.last = last;
        this.fullName = personFullName;
        this.fullNameReversed = personFullNameReversed;
    }
    

    这种写法的好处是,我们只需要创建一次方法函数,在构造函数中引用它们。那是否还有更好的方法呢?答案是肯定的。

    function Person(first, last) {
        this.first = first;
        this.last = last;
    }
    Person.prototype.fullName = function() {
        return this.first + ' ' + this.last;
    }
    Person.prototype.fullNameReversed = function() {
        return this.last + ', ' + this.first;
    }
    

    Person.prototype 是一个可以被Person的所有实例共享的对象。它是一个名叫原型链(prototype chain)的查询链的一部分:当你试图访问一个 Person 没有定义的属性时,解释器会首先检查这个 Person.prototype 来判断是否存在这样一个属性。所以,任何分配给 Person.prototype 的东西对通过 this 对象构造的实例都是可用的。

    这个特性功能十分强大,JavaScript 允许你在程序中的任何时候修改原型(prototype)中的一些东西,也就是说你可以在运行时(runtime)给已存在的对象添加额外的方法:

    s = new Person("Simon", "Willison");
    s.firstNameCaps();  // TypeError on line 1: s.firstNameCaps is not a function
    
    Person.prototype.firstNameCaps = function() {
        return this.first.toUpperCase()
    }
    s.firstNameCaps(); // SIMON
    

    有趣的是,你还可以给 JavaScript 的内置函数原型(prototype)添加东西。让我们给 String 添加一个方法用来返回逆序的字符串:

    var s = "Simon";
    s.reversed(); // TypeError on line 1: s.reversed is not a function
    
    String.prototype.reversed = function() {
        var r = "";
        for (var i = this.length - 1; i >= 0; i--) {
            r += this[i];
        }
        return r;
    }
    s.reversed(); // nomiS
    

    定义新方法也可以在字符串字面量上用(string literal)。

    "This can now be reversed".reversed(); // desrever eb won nac sihT
    

    你是否还记得之前我们说的 avg.apply() 中的第一个参数 null?现在我们可以回头看看这个东西了。apply() 的第一个参数应该是一个被当作 this 来看待的对象。下面是一个 new 方法的简单实现:

    function trivialNew(constructor, ...args) {
        var o = {}; // 创建一个对象
        constructor.apply(o, args);
        return o;
    }
    

    这并不是 new 的完整实现,因为它没有创建原型(prototype)链。想举例说明 new 的实现有些困难,因为你不会经常用到这个,但是适当了解一下还是很有用的。在这一小段代码里,...args(包括省略号)叫作剩余参数(rest arguments)。如名所示,这个东西包含了剩下的参数。

    因此调用

    var bill = trivialNew(Person, "William", "Orange");
    

    可认为和调用如下语句是等效的

    var bill = new Person("William", "Orange");
    

    apply() 有一个姐妹函数,名叫 call,它也可以允许你设置 this,但它带有一个扩展的参数列表而不是一个数组。

    function lastNameCaps() {
        return this.last.toUpperCase();
    }
    var s = new Person("Simon", "Willison");
    lastNameCaps.call(s);
    // 和以下方式等价
    s.lastNameCaps = lastNameCaps;
    s.lastNameCaps();
    

    9、内部函数
    内部函数可以访问父函数作用域中的变量,如果某个函数依赖于其他的一两个函数,而这一两个函数对你其余的代码没有用处,你可以将它们嵌套在会被调用的那个函数内部,这样做可以减少全局作用域下的函数的数量,这有利于编写易于维护的代码。

    function betterExampleNeeded() {
        var a = 1;
        function oneMoreThanA() {
            return a + 1;
        }
        return oneMoreThanA();
    }
    

    相关文章

      网友评论

          本文标题:Javascript学习笔记

          本文链接:https://www.haomeiwen.com/subject/tsoduftx.html