Hexo


  • 首页

  • 归档

JS中的概念解读

发表于 2017-08-24 | 分类于 JavaScript概念
  • 原型链

    js原型链

  • 字面量对象or对象字面量

  • 作用域

    • 全局作用域
    • 函数作用域
    • eval作用域(严格模式下)
  • 构造函数

    在JavaScript中,构造函数是用来创建原型链最常用的方法。构造函数如此流行的原因在于:它是创建类型的唯一途径。并且大部分引擎都对构造函数进行了高度优化。

  • _proto_和prototype

  • 原型继承机制(概念同『原型链』)

  • 显示原型&隐式原型

  • 构造函数与普通函数的区别?

    • 在命名规则上,构造函数一般是首字母大写,普通函数则是遵照小驼峰式命名法。

    • 在函数调用时:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      //构造函数
      function Egperson (name,age) {
      this.name = name;
      this.age = age;
      this.sayName = function () {
      alert(this.name);
      }
      }
      var person = new Egperson('mike','18'); //this-->person
      person.sayName(); //'mike'

      //普通函数
      function egPerson (name,age) {

      this.name = name;
      this.age = age;
      this.sayName = function () {
          alert(this.name);
       }
      

      }
      egPerson(‘alice’,’23’); //this–>window
      window.sayName(); //‘alice’
      ​

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
          
      - 构造函数内部会创建一个实例,调用普通函数时则不会创建新的对象。
      - 构造函数内部的this指向是新创建的person实例,而普通函数内部的this指向调用函数的对象(如果没有对象调用,默认为window)

      - 返回值方面,对于构造函数而言,如果构造函数内部有`return`语句,而且`return`后面跟着一个对象,`new`命令会返回`return`语句指定的对象;否则,就会不管`return`语句,返回`this`对象。

      - 立即执行函数

      **函数声明、函数表达式、匿名函数**

      - **函数声明**:使用function关键字声明一个函数,再指定一个函数名,叫函数声明。如下:

      ```javascript
      function fnName () {
      //...
      };

    • 函数表达式:使用function关键字声明一个函数,但未给函数命名,最后将匿名函数赋予一个变量,叫函数表达式,这是最常见的函数表达式语法形式。如下:

    1
    2
    3
    var fnName = function () {
    //...
    };
    • 匿名函数:使用function关键字声明一个函数,但未给函数命名,所以叫匿名函数,匿名函数属于函数表达式,匿名函数有很多作用,赋予一个变量则创建函数,赋予一个事件则成为事件处理程序或创建闭包等等。
    1
    2
    3
    function () {

    };

    函数声明和函数表达式不同之处在于:

    1. Javascript引擎在解析javascript代码时会‘函数声明提升’(Function declaration Hoisting)当前执行环境(作用域)上的函数声明,而函数表达式必须等到Javascirtp引擎执行到它所在行时,才会从上而下一行一行地解析函数表达式。
    2. 函数表达式后面可以加括号立即调用该函数,函数声明不可以,只能以fnName()形式调用 。

    区别如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    fnName();
    function fnName(){
    ...
    }
    //正常,因为‘提升'了函数声明,函数调用可在函数声明之前

    fnName();
    var fnName=function(){
    ...
    }
    //报错,变量fnName还未保存对函数的引用,函数调用必须在函数表达式之后
    var fnName=function(){
    alert('Hello World');
    }();
    //函数表达式后面加括号,当javascript引擎解析到此处时能立即调用函数
    function fnName(){
    alert('Hello World');
    }();
    //不会报错,但是javascript引擎只解析函数声明,忽略后面的括号,函数声明不会被调用
    function(){
    console.log('Hello World');
    }();
    //语法错误,虽然匿名函数属于函数表达式,但是未进行赋值操作,
    //所以javascript引擎将开头的function关键字当做函数声明,报错:要求需要一个函数名

    在理解了一些函数基本概念后,回头看看( function(){…} )()和( function (){…} () )这两种立即执行函数的写法,最初我以为是一个括号包裹匿名函数,并后面加个括号立即调用函数,当时不知道为什么要加括号,后来明白,要在函数体后面加括号就能立即调用,则这个函数必须是函数表达式,不能是函数声明。

    在function前面加!、+、 -甚至是逗号等到都可以起到函数定义后立即执行的效果,而()、!、+、-、=等运算符,都将函数声明转换成函数表达式,消除了javascript引擎识别函数表达式和函数声明的歧义,告诉javascript引擎这是一个函数表达式,不是函数声明,可以在后面加括号,并立即执行函数的代码。

    加括号是最安全的做法,因为!、+、-等运算符还会和函数的返回值进行运算,有时造成不必要的麻烦。

    不过这样的写法有什么用呢?

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

参考文档:

http://www.w3cplus.com/js/a-plain-english-guide-to-javascript-prototypes.html

http://javascript.ruanyifeng.com/oop/basic.html#toc1

JS中new关键字的执行流程

发表于 2017-08-24 | 分类于 JavaScript

来源:http://javascript.ruanyifeng.com/oop/basic.html

new命令简化的内部流程,可以使用如下代码表示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function _new(/*构造函数*/constructor,/*构造函数参数*/param){

//将arguments对象转为数组
var args = [].slice.call(arguments);
//取出构造函数
var constructor = args.shift();
//创建一个空对象,继承构造函数的prototype属性
var context = Object.create(constructor.prototype);
//执行构造函数
var result = constructor.apply(context,args);
//如果返回结果是对象,就直接返回。否则,返回context对象
return (typeof result === 'object' && result != null)?result:context;

}

//实例
var actor = _new(Person,'张三',28);

JavaScript箭头函数

发表于 2017-08-23 | 分类于 JavaScript
  1. 箭头函数的介绍
  2. 箭头函数的定义方式
  3. 箭头函数的优点
  4. 箭头函数与匿名函数的区别

箭头函数的介绍

​ 箭头函数(Arrow Function)是ES6标准新增的一种的函数 箭头函数就是定义时使用的是箭头。

箭头函数的定义方式

下面是其几种常见的定义方式:

  • 无函数名

    参数=>函数体(相当于匿名函数,省略了return和花括号)

    1
    x => x*5

    等价于

    1
    2
    3
    function(x){
    return x*5;
    }

    调用:

    1
    2
    let t = (x=>5*x)(8) //自运行数
    console.log(t);//输出40
  • 有函数名

    let 函数名 = 参数=>函数体

    1
    let f = x*x;

    等价于

    1
    2
    3
    let f = function(x){
    return x*x;
    }

    调用:

    1
    console.log(f(8)); //输出64
  • 函数体有多条语句

    不能省略函数体的花括号和return

    1
    2
    3
    4
    5
    6
    7
    x=>{
    if(x>0){
    return x*x;
    }else{
    return -x*x;
    }
    }
  • 函数有多个参数

    参数要用括号括起来

    1
    (x,y)=> x>y?x:y;

    定义并运行:

    1
    2
    3
    4
    5
    6
    7
    var t = ((x,y)=>x>y?x:y)(12,5);//立即运行
    console.log(t);

    //定义
    //var f = (x,y)=>x>y?x:y;
    //调用
    //console.log(f(12,5));
  • 无参

    参数要用括号括起来

    1
    ()=>24*3200;
  • 可变参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var f = (a...end)=>{ //相当于把省略号的所有值,作为数组end处理
    var sum = a;
    for(var i = 0;i<end.length;i++){
    sum +=end[i];
    }
    return sum;
    }

    console.log(f(1,2,3,4,5));//调用
  • 返回值是对象

    1
    2
    3
    4
    5
    var f = (id,name)=>({
    id:id,name:name
    }); //函数体必须要用()括起来 对象的花括号和函数体的花括号冲突

    console.log*(f("007","张无忌").id);

    ​

箭头函数的优点

对this转移的处理:箭头函数内部的this是词法作用域,由上下文确定。

原来的代码:

1
2
3
4
var that = this;
this.bannerTimer = setInterval(function(){
this.goStep();
},1000);

用箭头函数的代码:

1
2
3
this.bannerTimer = srtInterval(
()=>{this.goStep();}
,1000);

箭头函数与匿名函数的区别

箭头函数看上去是匿名函数的一种简写,但实际上,箭头函数和匿名函数有个明显的区别:

  1. 箭头函数内部的this是词法作用域,由上下文确定。
  2. 匿名函数中的this指向,一般指向window或者undefined。

JavaScript规则

发表于 2017-08-23 | 分类于 JavaScript

JavaScript有几条规则需要遵守:

  • 不要使用new Number()、new Boolean()、new String()创建包装对象;
  • 用parseInt()或parseFloat()来转换任意类型到number;
  • 用String()来转换任意类型到string,或者直接调用某个对象的toString()方法;
  • 通常不必把任意类型转换为boolean再判断,因为可以直接写if (myVar) {...};
  • typeof操作符可以判断出number、boolean、string、function和undefined;
  • 判断Array要使用Array.isArray(arr);
  • 判断null请使用myVar === null;
  • 判断某个全局变量是否存在用typeof window.myVar === 'undefined';
  • 函数内部判断某个变量是否存在用typeof myVar === 'undefined'。

常见问题

  • 任何对象都有toString()方法吗?

    null和undefined就没有!确实如此,这两个特殊值要除外,虽然null还伪装成了object类型。

  • 如果我们在使用Number、Boolean和String时,没有写new会发生什么情况?

    此时,Number()、Boolean和String()被当做普通函数,把任何类型的数据转换为number、boolean和string类型(注意不是其包装类型)。

闭包函数

发表于 2017-08-21 | 分类于 JavaScript

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。

变量的作用域

JS变量作用域分两种:全局变量和局部变量。函数内部可以直接读取全部变量,但是外部无法直接读取函数内部声明的局部变量。

函数内部声明变量必须使用var声明,直接使用的变量默认为全局变量(strict模式下 必须通过var声明)。

1
2
3
4
5
6
var name = "小明";
function getName(){
alert(name); //小明
var age = 23;
}
alert(age); //age is not defined

如何通过从外部函数读取内部函数的局部变量

1
2
3
4
5
6
7
8
9
10
var name = "小明";
function getName(){
alert(name); //小明
var age = 23;
return function rAge(){
return age;
};
}
var result = getName();
alert(result());

根据js的作用域规定,内部函数能够访问到外部函数的局部变量。因此,我们可以在getName()这个方法中返回一个函数rAge(),然后在该函数中将getName()函数的局部变量进行返回。

这样,我们就在函数外调用到了函数内的变量!

什么是闭包函数?

闭包是指可以访问另一个函数作用域变量的函数,一般是定义在外层函数中的内层函数。如上一问题中的rAge()函数就是闭包函数。

我们可以把闭包简单理解成定义在一个函数内部的函数。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

闭包的用途

  1. 可以读取函数内部的变量

  2. 让这些变量的值始终保持在内存中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function f1(){
        var n=999;
        nAdd=function(){
    n+=1;
    }
        function f2(){
          alert(n);
        }
        return f2;
      }
      var result=f1();
      result(); // 999
      nAdd();
      result(); // 1000

    在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。

    为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

    这段代码中另一个值得注意的地方,就是”nAdd=function(){n+=1}”这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

使用闭包需要注意的事项

  • 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
  • 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

JS中字符与ASCII码互转

发表于 2017-08-21 | 分类于 JavaScript

一、常用ASCII码

  • 大写字母A 到Z 的值是从65 到90
  • 小写字母a 到 z 的值是从91 到 122

二、相互转换

  • 字符转ascii码:用charCodeAt();
  • ascii码砖字符:用fromCharCode();

JavaScript基础知识

发表于 2017-08-15 | 分类于 JavaScript

JavaScript的注释与分号

  • // 用来进行单行注释
  • /**/ 用来进行多行注释
  • ; 分号用在语句结束,如果省略,则由解析器确定语句的结尾。(为了保证代码的规范性,建议手动在代码结尾添加分号)

JavaScript的语法

ECMAScript中的一切(变量、函数名和操作符)都区分大小写

JavaScript的标识符

  • 什么是标识符

    变量、函数、属性的名字,或者函数的参数

  • 标识符的命名规则

    1. 由字母、数字、下划线( _ )或美元符号( $ )组成
    2. 不能以数字开头
    3. 不能使用关键字、保留字作为标识符

什么是变量

​ ECMAScript的变量是松散类型

​ 松散类型:可以用来保存任何类型的数据

​ 换句话说,每个变量仅仅是一个用于保存值的占位符而已

变量的声明与赋值

  1. 变量声明:

    变量的声明要使用var操作符

    语法: var 变量名

人工智能&机器学习&深度学习的关系

发表于 2017-08-15 | 分类于 人工智能

如图

Image.jpg

123

HaoZ

This is a simple website, I will try record something that I studying!

28 日志
14 分类
43 标签
RSS
© 2018 HaoZ
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4