老司机Studio 第五章

高级函数

  • sort函数
var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
    if (x < y) {
        return 1; // 返回1代表需要位置互换
    }
    if (x > y) {
        return -1; // 返回-1代表不需要互换
    }
    return 0;
}); // [20, 10, 2, 1]
  • filter函数
var arr = ['A', 'B', 'C'];
var r = arr.filter(function (element, index, self) {
    console.log(element); // 依次打印'A', 'B', 'C'
    console.log(index); // 依次打印0, 1, 2
    console.log(self); // self就是变量arr
    return true;
});

var arr = ['apple', 'strawberry', 'banana', 'pear', 'apple', 'orange', 'orange', 'strawberry'];
var r = arr.filter(function (element, index, self) {
    return self.indexOf(element) === index; // indexOf函数获取array中某个元素的下标
});

作用域

在JavaScript中,我们可以将作用域定义为一套规则,这套规则用来管理引擎如何在当前作用域以及嵌套的子作用域中根据标识符名称进行变量查找。
这里的标识符,指的是变量名或者函数名。

作用域与执行上下文是完全不同的两个概念。
JavaScript代码的整个执行过程,分为两个阶段:

代码编译阶段与代码执行阶段
编译阶段由编译器完成,将代码翻译成可执行代码,这个阶段作用域规则会确定,对于函数,是函数的定义过程。
执行阶段由引擎完成,主要任务是执行可执行代码,执行上下文在这个阶段创建,是函数的调用过程。

function a(){ //函数定义
  console.log(1);
}
a() //函数调用
编译与执行

执行上下文

执行上下文(Execution Context)。
每次当控制器转到可执行代码的时候,就会进入一个执行上下文。执行上下文可以理解为当前代码的执行环境,它会形成一个作用域。
全局环境:JavaScript代码运行起来会首先进入该环境
函数环境:当函数被调用执行时,会进入当前函数中执行代码

var color = 'blue';

function changeColor() {
    var anotherColor = 'red';

    function swapColors() {
        var tempColor = anotherColor;
        anotherColor = color;
        color = tempColor;
    }

    swapColors();
}

changeColor();
第一步:全局上下文入栈
第二步:changeColor的执行上下文入栈
第三步:swapColors的执行上下文入栈
第四步:swapColors的执行上下文出栈
第五步:changeColor的执行上下文出栈
整个过程

函数定义阶段——闭包

作用域链:是由当前环境与上层环境的一系列变量对象组成,它保证了当前执行环境对符合访问权限的变量和函数的有序访问。

var a = 20;

function test() { // 执行上下文A
    var b = a + 10;

    function innerTest() { // 函数B
        var c = 10;
        return b + c;
    }

    return innerTest();
}

test();
作用域链

闭包:设有函数B是在执行上下文A内定义的。如果B内部访问了A内的变量对象,则产生闭包。
闭包的重要特点是,执行上下文A出栈后不会被内存回收,也就是说B依然可以访问到原来定义时的数据。�

var fn = null;
function foo() {
    var a = 2;
    var c = 100;
    function innnerFoo() { 
        // console.log(c); // 在这里,试图访问函数bar中的c变量,会抛出错误
        console.log(a);
    }
    fn = innnerFoo; // 将 innnerFoo的引用,赋值给全局变量中的fn
}

function bar() {
    var c = 100;
    fn(); // 此处的保留的innerFoo的引用
}

foo();
bar();
在chrome中观察闭包

函数执行阶段——变量对象

执行上下文的创建

变量对象的创建过程:
变量对象的创建,依次经历了以下几个过程。

  1. 建立arguments对象。检查当前上下文中的参数,建立该对象下的属性与属性值。
function test(x,y){
  console.log(arguments);
  console.log(x);
  console.log(y);
}
test(1,2);
  1. 检查当前上下文的函数声明,也就是使用function关键字声明的函数。在变量对象中以函数名建立一个属性,属性值为指向该函数所在内存地址的引用。如果函数名的属性已经存在,那么该属性将会被新的引用所覆盖

  2. 检查当前上下文中的变量声明,每找到一个变量声明,就在变量对象中以变量名建立一个属性,属性值为undefined。如果该变量名的属性已经存在,为了防止同名的函数被修改为undefined,则会直接跳过,原属性值不会被修改。

image.png
// demo1
function foo() { console.log('function foo') }
var foo = 20;
console.log(foo); // 20

console.log(foo); // function foo
function foo() { console.log('function foo') }
var foo = 20;
// demo2
function test() {
    console.log(a);
    console.log(foo());
    
    var a = 1;
    function foo() {
        return 2;
    }
}
test();

// demo3
function test() {
    console.log(foo);
    console.log(bar);
    var foo = 'Hello';
    console.log(foo);
    var bar = function () { // 函数的赋值
        return 'world';
    }

    function foo() { // 函数的声明
        return 'hello';
    }
}
test();

var/let/const
var 声明的变量在当前函数内一直存在。
function (){
...生效...
}
let / const 声明的变量只在当前代码块
({}包裹起来的为一个代码块,但不是只有{}产生代码块,如if后可以没有{}的情形)
中存在,前者为变量,后者为常量(ES6)。

function test(){
  {
    let a = 1;
    var b = 1
  }
console.log(b)
console.log(a)
}

延时执行,定时执行

  • setTimeout
for(var i = 0; i<5; i++){
  setTimeout(function(){
    console.log(i)
  }, i*1000)
}
// 5 5 5 5 5

for (var i=1; i<=5;  i++) { 
    setTimeout((function(i) {
        return function() {
            console.log(i);
        }
    })(i), i*1000 );
}
// 0 1 2 3 4

for(let i = 0; i<5;i++){
  setTimeout(function(){
    console.log(i)
  }, i*1000)
}
// 0 1 2 3 4
  • setTimeInterval
  • clearTimeInterval

操作DOM

  • innerHTML
  • innerText
  • style
  • appendChild
<p id="js">JavaScript</p>
<div id="list">
    <p id="java">Java</p>
    <p id="python">Python</p>
    <p id="scheme">Scheme</p>
</div>
var js = document.getElementById('js'),
list = document.getElementById('list');
list.appendChild(js);
  • document.createElement
  • insertBefore(newElement, referenceElement)
  • removeChild

作业

  1. 写出“函数执行阶段——变量对象”这一节的demo3的执行顺序。
  2. 使用原生javascript实现一个to-do list


    to-do List
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352

推荐阅读更多精彩内容