JS基础笔记第一记

122 阅读4分钟

JS的基础笔记


学习的时候写了一些笔记,然后就想花时间整理一下,一方面是加深理解和记忆,另一方面是想系统的整理一下,参考的来源我都会写下来。


我的笔记目录

  • 原型和原型链
  • 作用域和作用域链
  • 闭包

1,原型和原型链

1.1 原型

原型:构造函数都有一个原型(prototype),指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承.
访问原型:1,构造函数(constructor)通过.prototype。2,实例通过._proto_,实例会继承原型的属性和方法。

1.2 原型链

比如说,a继承b, b继承c, a的原型就会包含b的原型,b的原型包含c的原型,从来就形成了原型链, 下图Cat继承了animal的原型。打印的是一个Cat实例

参考来源:www.ruanyifeng.com/blog/2010/0…

2,作用域和作用域链

2.1 变量作用域: 变量作用的区域

作用域只作用在函数的内部,外部不可访问

function foo() {
    var x = 1;
    function bar() {
        var y = x + 1; // foo函数内部的bar函数可以访问foo的变量X
    }
    var z1 = x + 1 // foo函数内部也可以访问foo的变量X
    var z2 = y + 1; // ReferenceError! bar函数外部不可以访问bar的变量y!
}

2.2 作用域链 : 从函数内部到外部开始找变量,直到找到为止,如果在window这一层都没有找到,那该变量is not defined

var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f();
}
checkscope(); //local scope

checkscope()先从函数内部开始找scope这个变量,找到了就会停止。所以我们得到的scope是函数内部的scope,如果函数内部没有scope,才会去函数外面找。

var scope = "global scope";
function checkscope(){
    function f(){
        return scope;
    }
    return f();
}
checkscope(); //global scope

参考来源:
www.liaoxuefeng.com/wiki/102291…
github.com/mqyqingfeng…

3,闭包

这是一个需要了解内存的问题,js里面的存储方式分两种。还有,我也不懂它为什么要叫闭包,明明是去函数内部偷变量。因为作用域的关系,我们本来是不可以在函数外部访问函数内部的变量,但是通过闭包,可以,偷。

3.1 关于内存 (关联请看下面3.3.2)

数字,字符串,布尔值这类数据类型在内存中存的真实的值, 
对象,函数在内存中存的是地址

3.2 闭包是通过其他函数的返回值得到其他函数内部变量的函数

function f1() {
    var n = 999;
    function f2() {
        console.log(n)
    }
    return f2;
}
var result = f1();
result(); // 999

本来函数外部是不能访问函数内部变量的,闭包就可以把变量拿出来

3.3 闭包的坑点

3.3.1 返回的函数并没有立刻执行,而是直到调用了才执行


function count() {
    var arr = [];
    for (var i=1; i<=3; i++) {
        arr.push(function () {
            return i * i; 
        });
    }
    return arr;
}

var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
f1(); // 16
f2(); // 16
f3(); // 16

执行count函数,返回的是一个函数数组,数组里面的每个函数都还没有被执行,所以匿名函数里面的return i*i是没有执行的,后面执行f1/f2/f3的时候,函数会根据作用域链查找i,而那时i的值已经是4了,所以才会都得到16。如果要固定参数的话,可以按照下面这样

function count() {
    var arr = [];
    for (var i=1; i<=3; i++) {
        arr.push((function (n) {
            return function () {
                return n * n;
            }
        })(i)); //push进去的是一个执行的匿名函数的返回值,也就是一个有固定参数的函数
    } 
    return arr;
}

var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];

f1(); // 1
f2(); // 4
f3(); // 9

3.3.2 函数是一个单独的值,函数在内存存的是地址,它可以在不同的环境(this)执行。所以可能闭包在执行的时候,因为this的不同会导致结果不同。

 第一种
 
  var name = "The Window";
  var object = {
      name: "My Object",
      getNameFunc: function () {
          return function () {
              return this.name;
          };
      }
 };
 alert(object.getNameFunc()()) //The Window
 
 第二种
 
 var name = "The Window";
    var object = {
        name: "My Object",
        getNameFunc: function () {
            var that = this;
            return function () {
                return that.name;
            };
        }
    };
alert(object.getNameFunc()());//My Object

特别特别需要注意,这两个由object.getNameFunc()得到的函数的this指向全局对象,也就是window。那结果为什么不同,就是因为第二个函数在object.getNameFunc()执行的时候函数的this指向object。如果还不清楚,那就拆开看

object.getNameFunc()() ===(等同于)   var fun = object.getNameFunc()     fun()

var fun = object.getNameFunc() //只是执行getNameFunc函数,并没有给定fun函数的this指向
fun() // 本来两个函数this都是指向window,第二种在object.getNameFunc()执行的时候函数的this指向Object

参考来源:
www.ruanyifeng.com/blog/2009/0… (阮一峰老师的网络日志实在是对新手非常,特别,尤其地友好)
www.liaoxuefeng.com/wiki/102291… (廖雪峰老师的js教程也是很好的,比较全面)

欢迎提出改正与建议