JS语法


JavaScript基本概念、基础数据类型、运算符、流程控制语句。


一、CSS和JS在网页中的放置顺序是怎样的?

CSS和JS在网页中的顺序是非常重要的,它会对其他资源的加载顺序产生影响。

  • CSS
    CSS代码一般放在head标签当中,用link标签将样式放在顶部。网页渲染时,是先解析HTML标签,生成DOM树,再解析CSS标签,构成CSSOM树,然后再把DOM和CSSOM组合成渲染树。如果把CSS放在后面,可能会出现白屏问题或者FOUC (Flash of Unstyled Content) 无样式内容闪烁。
  • JS
    JS文件需要被HTML引用才能在浏览器当中运行,而在HTML当中有不同的方式来引用脚本文件,这些方式就有可能带来性能的问题。
    引用JS脚本文件必须要使用

    如果没有async和defer属性,浏览器会立即加载并执行指定的脚本。这里的“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。

    • async
    
    

    async是html5中新增的属性,它的作用是能够异步加载和执行脚本,不会因为加载脚本而阻塞页面的加载,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。一旦加载到就会立刻执行,很有可能不是按照原本的顺序来执行的。如果js前后有依赖性,用async,就很有可能出错。

    • defer
    
    

    如果script加了defer属性,即使放在head里面,它也会在HTML解析完成之后再去执行,就相当于把script放到了页面底部。有 了defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。也就是说JS的加载不会阻塞页面的渲染和资源的加载。但defer会按照原本的JS的顺序执行,所以如果前后有依赖关系的JS可以放心使用。

    • 比较async和defer
    • 相同点
      • 加载文件时不会阻塞页面的渲染。
      • 对于inline的script无效。
      • 使用这两个属性的脚本中不能调用document.write方法。
      • 有脚本的onload的事件回调。
    • 不同点
      • async不保证原本的执行顺序;defer脚本延迟到文档解析和显示后执行,会按照原本的顺序执行。
      • HTML5.0中定义了async,HTML4.0中定义了defer。

    详细资料还可以参考script的defer和async。

    四、简述网页的渲染机制。

    • 解析HTML标签, 构建DOM树。
    • 解析CSS标签, 构建CSSOM树。
    • 把DOM和CSSOM组合成 渲染树 (render tree)。
    • 在渲染树的基础上进行布局, 计算每个节点的几何结构。
    • 把每个节点绘制到屏幕上 (painting)。

    详细资料可以参考:
    前端必读:浏览器内部工作原理
    How browsers work

    五、JavaScript 定义了几种数据类型? 哪些是简单类型?哪些是复杂类型?

    JavaScript语言的每一个值都属于某一种数据类型。JavaScript的数据类型一共有六种,分为五种简单数据类型(也称为基本数据类型):

    • 数值(number):整数和小数,比如:1和3.14 。
    • 字符串(string):字符组成的文本,比如:"Hello World"。
    • 布尔值(boolean):truefalse两个特定的值。
    • undefined:表示未定义或者不存在,即此处目前没有任何值。
    • null:表示空缺,即此处应该有一个值,但目前为空。

    还有一种复杂数据类型—object,也就是对象,它表示各种值组成的集合。对象又可以分成三个子类型。

    • 狭义的对象(object)
    • 数组(array)
    • 函数(function)
      通常将数值、字符串、布尔值称为原始类型(primitive type)的值,即它们是最基本的数据类型,不能再细分。而将对象称为合成类型(complex type)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。至于undefinednull,一般将它们看成两个特殊值。

    六、NaN、undefined、null分别代表什么?

    • NaN
      NaN的含义是“Not a Number”,表示非数字。这个数值用于表示一个本来要返回数值的操作数未返回数值的情况(这样就不会抛出错误)。NaN有两个不一般的特点,第一,NaN和任何值都不相等,包括自己;第二,任何涉及NaN的操作(比如NaN/1)都会返回NaN。
      针对NaN的这两个特点,ECMAScript定义了isNaN()函数。它只有一个参数,这个参数可以是任何类型,该函数会帮我们确定这个参数是否“不是数值”。


      JS语法_第1张图片
      控制台测试
    • undefined
      undefined表示不存在值,就是此处目前不存在任何值。典型用法是:
    • 变量被声明了,但没有赋值时,就等于undefined。
    • 调用函数时,应该提供的参数没有提供,该参数等于undefined。
    • 对象没有赋值的属性,该属性的值为undefined。
    • 函数没有返回值时,默认返回undefined。


      JS语法_第2张图片
      控制台测试
    • null
      null表示空值,即该处的值现在为空。典型用法是:
    • 作为函数的参数,表示该函数的参数是一个没有任何内容的对象。
    • 作为对象原型链的终点。

    七、typeof和instanceof的作用和区别?

    因为ECMAScript是松散型的,所以需要一种手段来检测给定变量的数据类型。JS中有三种方法来确定一个值到底是什么类型。分别为:typeof运算符、instanceof运算符以及`Object.prototype.toString方法。

    • typeof
      typeof运算符可以返回一个值的数据类型,可能有以下结果。
    • 原始类型
      数值、字符串、布尔值分别返回numberstringboolean
      JS语法_第3张图片
    • 函数
      函数返回function
    • undefined
      undefined返回undefined

      利用这一点,typeof可以检查一个没有声明的变量而不报错。

      事实上,这个特点也经常用于判断语句当中。
    • 其他
      除此以外,其他的都是返回object
      JS语法_第4张图片
    • instanceof
      在使用typeof采用引用类型存储值时,无论引用的是什么类型的对象,都会返回object。针对这个问题,ECMAScript引入了instanceof来解决这个问题。与typeof不同,instanceof只有truefalse两个输出。

      oStringObject 是 String 对象的实例,因此结果是true。所以在 typeof 方法返回 "object" 的情况下,instanceof 方法还是很有用的。
      更详细的用法可以参考JavaScript instanceof 运算符深入剖析。

    八、代码

    1. 完成如下代码判断一个变量是否是数字、字符串、布尔、函数 (难度*)。
      ps: 做完后可参考 underscore.js 源码中部分实现。
    function isNumber(el){
     // todo ...
    }
    function isString(el){ 
    //todo ...
    }
    function isBoolean(el){ 
    //todo ...
    }
    function isFunction(el){ 
    //todo ...
    }
    var a = 2,
     b = "jirengu",
     c = false;
    alert( isNumber(a) ); //true
    alert( isString(a) ); //false
    alert( isString(b) ); //true
    alert( isBoolean(c) ); //true
    alert( isFunction(a)); //false
    alert( isFunction( isNumber ) ); //true
    

    DEMO1
    DEMO2

    2.以下代码的输出结果是?(难度**)

    console.log(1+1);    //2。 加法计算
    console.log("2"+"4");     //24。 有一个是字符串,转换为字符串的拼接。
    console.log(2+"4");    //24。 有一个是字符串,转换为字符串的拼接。
     console.log(+new Date());    //1471048600952。 获得当日的日期,用new Date() 参与计算会自动转换为从1970.1.1开始的毫秒数。
    console.log(+"4");    //4。  只有一个字符串,会转换成数字。
    
    JS语法_第5张图片
    运行结果

    JS中的运算符主要用于连接简单的表达式,组成一个复杂的表达式。常见的有算数表达式、比较表达式、逻辑表达式、赋值表达式等,也有单目运算符,指操作原始表达式。大多数运算符都由标点符号组成(+、>=、!),也有关键字表示的运算符,如typeof、delete、instanceof等。
    在JavaScript中运算符通常会根据需要对操作数进行类型转换,乘法操作符*希望操作数是数字,但是 "3" * "5" 也是合法的,JavaScript会自动将其转换为数字计算,返回Number 15。
    有些操作符对不同的数据类型有不同的含义,比如:+

    • 在两个操作数都是数字的时候,会做加法运算。
    • 两个参数都是字符串或在有一个参数是字符串的情况下会把另外一个参数转换为字符串做字符串拼接。
    • 在参数有对象的情况下会调用其valueOf或toString。
    • 在只有一个字符串参数的时候会尝试将其转换为数字。
    • 在只有一个数字参数的时候返回其正数值。

    3.以下代码的输出结果是? (难度***)

    var a = 1;
    a+++a;  //3
    typeof a+2;  //number2
    

    a+++a表达式当中,后置递增的优先级最高。所以相当于(a++)+a。a一开始赋值为1,a++表示先赋值再自增,所以a++的计算结果为1,且此时a等于2。所以a+++a表达式的计算结果为3。
    typeof a+2中,typeof的优先级比“+”高,所以它会先计算typeof a,得到的输出是"number"。然后是一个字符串加上一个数字,会把数字转换成字符串。所以得到的输出为"number2"的字符串。

    JS语法_第6张图片
    运行结果

    运算符优先级
    4.遍历数组,把数组里的打印数组每一项的平方(难度**)。

    var arr = [3,4,5]
    // todo..// 
    输出 9, 16, 25 
    
    JS语法_第7张图片
    运行结果

    5.遍历 JSON, 打印里面的值(难度**)。

    var obj = { 
    name: 'hunger', 
    sex: 'male', 
    age: 28
    }
    //todo ...
    // 输出 name: hunger, sex: male, age:28
    
    JS语法_第8张图片
    运行结果

    6.下面代码的输出是? 为什么 (难度***)

    console.log(a);
    var a = 1;
    console.log(a);
    console.log(b);
    

    JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,给他初始值undefined,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升。
    所以在上面的代码中,变量a先被声明,再执行console.log(a);,也就是相当于执行了var a; console.log(a);。因为此时a没有赋值,所以console.log(a);结果为undefined。然后a被赋值为1,再执行console.log(a);,所以console.log(a);结果为1。最后,console.log(b);,由于b变量不存在,所以结果报错。

    JS语法_第9张图片
    运行结果

    这也正体现了变量提升的作用。我们在使用一个变量之前必须声明变量,但是由于变量提升,我们如果声明了变量,即使在声明语句前使用也是可以的,只不过其值是初始值undefined。

你可能感兴趣的:(JS语法)