【javascript基础知识】

javascript基础知识

  • 前提
    • 书写位置
    • 基础知识
    • 数 组
    • 函 数
    • 预解析
    • 对 象

前提

JavaScript是脚本语言,是一种运行在浏览器中的解释型的编程语言。
1、浏览器分成两部份:渲染引擎和JS引擎(解析器)。
前者解析html和css,后者读取js代码,执行代码时逐行解释每一句源码(转换为机器语言)如chrome的v8。

2、JS的组成:ES、dom和bom
ES:规定基础语法。
DOM:文档对象模型,通过其提供的接口可以对页面上各种元素进行操作。
BOM:浏览器对象模型, 提供了独立于内容的,可与浏览器窗口进行互动的对象结构。(如弹出窗、。控制浏览器跳转、获取分辨率等。)

书写位置

  • 行内式的js:直接写到元素内部,如οnclick=“alert(‘aa’)”
  • 内嵌式的js: head内部写入,中间写入就JS代码
  • 外部的js: 注意:中间不要写代码,适用于js代码比较多的情况
  • 位置不同,解析先后会有所不同。
    相关链接: JS放在文件头部还是尾部.

关于浏览器渲染
相关链接: 浏览器渲染原理.

  • 服务器端Response响应后,浏览器端拿到代码后,在内存条中开辟出一块栈内存,给代码执行提供环境。同时分配一个主线程去一行行解析执行代码。(进栈执行,执行完就出栈)
  • 当浏览器遇到link/script/img等请求后,都会开辟新的线程去加载资源文件
  • 自上而下,解析html生成DOM树
  • 构建Render树:接下来不管是内联式,外联式还是嵌入式引入的CSS样式会被解析生成CSSOM树,根据DOM树与CSSOM树生成另外一棵用于渲染的树——渲染树(Render tree)
  • 布局Render树:计算在设备视口(viewport)内的确切位置和大小,这个计算阶段叫回流(Layout)
  • 绘制Render树 - 最后遍历渲染树并用UI后端层将每一个节点绘制出来

其中,可做性能优化:减少HTTP的请求次数和大小(比如把所有css合成为一个)

  1. 资源合并压缩
  2. 图片懒加载
  3. 音视频走流文件
    等方法

defer和async

基础知识

  1. 输入框:prompt(’ ‘);
    弹出提示框:alert(’ ‘);
    控制台输出:console.log(’ ');
  2. 变量的使用 var声明
    特殊情况:只声明不赋值——结果为undefined;不声明不赋值——报错;不声明直接赋值——可以但不建议
  3. 数据类型:js的变量数据类型只有在数据运行中,根据等号右边的值来确定。js是动态语言,变量的数据类型可以变化。

若有变量打算存储为对象(Object),但暂时没想好存啥,可以给null
如 var aa=null;

原始数据类型 栈内存
数字型 Number类型 整数、小数点、八进制和十六进制(程序会转化成十进制)等,NaN非数字:isNaN()用来判断非数字,是数字返回false
字符串型String类型 一般推荐使用单引号,转义符:\n换行,\t tab缩进
布尔型Boolean true当1,false当0
Undefined 未定义(:undefined和数字相加结果为NaN)
Null 空值
引用数据类型 堆内存
对象
数组
函数

①原始数据类型:

     直接存储在栈(stack)中的简单数据段,占据空间小、大小比较稳定。
     属于被频繁使用数据,所以放入栈中存储;

②引用数据类型:

     存储在堆(heap)中的对象,占据空间大、大小不固定。
     在栈内存中只是存了一个地址来表示对堆内存中的引用。
     堆内存是无序存储,可以根据引用直接获取。
     
     引用数据类型进行复制时,系统也会自动为新的变量在栈内存中分配一个值,但这个值仅仅是一个地址。
     也就是说,复制出来的变量和原有的变量具有相同的地址值,指向堆内存中的同一个对象。

栈区(stack):编译器自动分配释放,存放函数的参数值,局部变量的值 等,操作方式类似于数据结构的栈。
堆区(heap):一般是由程序员分配释放,若程序员不释放的话,程序结束时可能由OS回收,值得注意的是他与数据结构的堆是两回事,分配方式倒是类似于数据结构的链表。

当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。所以,JavaScript中对引用数据类型的操作都是操作对象的引用而不是实际的对象。可以理解为,栈内存中保存了一个地址,这个地址和堆内存中的实际值是相关联的。

  1. typeof():获取变量数据类型
  2. 数据类型转换
    转换成字符串型:var str=num.toString(); 或 console.log(String(num));
    转换成数字型:parseInt( ‘78’ ); parseFloat(‘3.14’); Number(‘123’); 隐式转换(利用算术运算- */):console.log(‘123’ - 1);
    转换成布尔型:console.log(Boolean(‘123’));除了‘ ’、NaN、null、undefined外其他都返回为true
  3. 编译器解释器的区别:
    前者在执行代码前进行编译(相当于做菜),后者在运行时及时解释并立即执行(相当于吃火锅)
  4. 标识符(取的名)不能是关键字(如if、for、break、default等)和保留字(如const、public等 )
  5. ++aa++:单独使用时效果一样;否则++a自加1再赋值,a++先赋值再自加1
  6. 逻辑与短路运算(表达式1 && 表达式2):如果表达式1结果为真,则返回表达式2;若为假,则返回表达式2.
    逻辑或短路运算(表达式1 || 表达式2):如果表达式1结果为真,则返回表达式1;反之亦然。
  7. 流程控制
    ① if…else if…else: 只会有一个代码块被执行,一旦代码块执行了,则直接结束语句
    ② switch(expression){
    case judgement1:…break;
    case judgement2:…break;

    default:…break;
    } //数据类型值要一样才能匹配上
    ③ while(条件表达式){} //先判断条件表达式,若为true则执行循环体;
    ④ do{ }while(条件表达式); //先执行一次循环,再判断条件表达式
    三元表达式: 条件表达式?表达式1:表达式2
    ⑥continue关键字:立即跳出本次循环,进入下一循环。
    break:立即跳出整个循环。

数 组

数组 操作
创建数组 var a=new Array();var a=[ ‘xiao’,‘xiaohong’]
添加参数 arr.concat( 9,[10,13]);这个方法会先创建当前数组的副本,然后将接收到的参数添加到这个副本的末尾
判断类型 Array.isArray(arr); 或者 console.log(arr instanceof Array)
数组变字符串 arr.join( ); arr.join( ’ 、’) ; arr.toString( );
翻转 arry.reverse( )
排序 console.log(‘数组排序-降序:’ +arr.sort(function(a, b) { …return b - a}));
数组截取和替换 '截取从索引值3开始到最后:arr.slice(3)); 截取从索引值1开始获取三个元素:arr.slice(1, 3)); 截取获取最后2位:arr.slice(-2)); 从索引值1开始的两个元素替换成aaa:arr.slice(1, 2, ‘aaa’);
索引位置 indexOf/lastIndexOf索引位置,没有则返回-1
数组遍历 //every遍历数组:arr.every(function(a, b, c) {…return true; }); 规则:c[b] = a; //forEach方法(无返回值):arr.forEach(function(x, index, a){ });//map遍历数组(返回数组):var arr2 = arr.map(function(item){return item*item;});
filter过滤器 var newArr=arr.filter ( function(element,index,arr){ return …;}); 返回满足过滤条件组成的数组

相关链接: 数组方法总结.
数组方法2

函 数

  1. 声明函数:
    ①function fn( ){ }
    ②ES6中方式:( )=>{ }
    ③函数表达式(匿名函数),将函数存到变量/数组里(调用时要写括号,且调用要放在声明的后面): var func = function( ) { };
  2. 调用:
    ① fn();
    ②在事件中调用,直接写变量名,不使用括号,如:document.οnclick=fn;
  3. 参数
    形参:形式上的参数——给函数声明一个参数;
    实参:实际的参数——在函数调用时给形参赋的值
function func(形参1,形参2){
    //函数执行代码
 }
 
func(实参1,实参2);//调用时传参
  1. arguments的使用
    当不确定有多少个参数时用arguments来获取,它是当前函数的一个内置对象,所有函数内都内置了一个arguments对象,该对象中存储了传递的所有实参。
  • arguments展示形式是伪数组
    • 具有数组的length属性
    • 按索引方式存储
    • 没有真正数组的一些方法(如pop() 、 push())
    • 可按数组方式遍历arguments

只有函数才有arguments对象,且每个函数内都内置了这个arguments对象。可以和 rest 联合使用。
如:function aaa(a,b, …rest){ }

  1. 作用域
    全局变量:在全局作用域下的变量; 如果在函数内部,没有声明直接赋值的变量也叫全局变量。
    局部变量:在局部作用域(函数)下的变量,形参也可以看作局部变量。

全局变量只有浏览器关闭的时候才销毁,比较占内存资源;
局部变量当我们程序执行完毕时就会销毁,比较节约内存资源。

ES6中新增了块级作用域,使用let声明的变量只能在块级作用域里访问,有“暂时性死区”的特性(也就是说声明前不可用)。
块作用域由 { } 包括,if语句和for语句里面的{ }也属于块作用域。

var 定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。
let 定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。
const 用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。

  • JS实际上只有一个全局作用域,若变量在全局作用域内都没查找到,会报错 RefrenceError

规范

由于所有全局变量都绑定在window上,如果不同的js文件,使用了相同的全局变量,会产生冲突=>如何减少冲突?

 //唯一全局变量(为了不直接绑定在window上)
 var a = {};

 //定义全局变量
 a.name = '华华';
 a.add = function(x,y){
     return x+ y;
 }
  • ES6 的 let 关键字能解决局部作用域冲突问题,建议用 let 去定义局部作用域的变量
  1. 作用域链:内部函数访问外部函数的变量,采用的是链式查找方式决定取哪个值。(就近原则

预解析

  1. JS解析器分两步:预解析和代码执行
  • 预解析:js引擎会把js里面所有的var以及function提到当前作用域的最前面。
    预解析分为变量预解析(变量提升)和函数预解析(函数提升)。
    (1)变量预解析:所有的变量声明提升到当前作用域的最前面,不提升赋值操作。
    (2)函数预解析:所有的函数声明提升到当前作用域的最前面,不调用函数。
  • 代码执行:按照代码书写顺序从上至下执行

对 象

  1. 对象:是一组无序的相关属性方法的集合。
  2. 创建对象:
    ①利用对象字面量: (方法冒号跟的是一个匿名函数
var obj={ 
   uname:'zhangsan',
   age:18,
   sayhi:function(){
         console.log('方法');
   }
};

②利用new Object:(等号赋值 的方法添加对象的属性和方法)

var obj=new Object( );  //创建空对象
obj.name='zhangsan';
obj.age=18;
obj.sayhi=function(){ 
      console.log('方法');
};

③利用构造函数:
前面两种方式一次只能创建一个对象,而构造函数里面封装的是对象.
构造函数不需要return就可以返回结果
调用构造函数必须使用new(该过程叫对象实例化

格式: function 构造函数名(){
             this.属性=值;
             this.方法=function();
 }
     var aa= new 构造函数名();

④利用原型prototype对象

  • 原型链
    相关链接: 原型和原型链.
         //这是一个构造函数
     	function Foo(name,age){
     		this.name=name;
     		this.age=age;
     	}
     	/*根据要点3,所有的函数都有一个prototype属性,这个属性是一个对象
     	再根据要点1,所有的对象可以自由扩展属性
     	于是就有了以下写法*/
     	Foo.prototype={
     		// prototype对象里面又有其他的属性
     		showName:function(){
     			console.log("I'm "+this.name);//this是什么要看执行的时候谁调用了这个函数
     		},
     		showAge:function(){
     			console.log("And I'm "+this.age);//this是什么要看执行的时候谁调用了这个函数
     		}
     	}
     	var fn=new Foo('小明',19)
     	/*当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会去它
     	构造函数的'prototype'属性中去找*/
     	fn.showName(); //I'm 小明
     	fn.showAge(); //And I'm 19
    
    使用原型链,我们只需要在构造函数中给属性赋值就行了,方法可以写在prototype中,可以节省很多资源。
    
  1. 使用对象
    • 调用对象的属性采用 对象名 . 属性名 或者 对象名[‘属性名’]
    • 调用对象的方法 对象名.方法名( ) 不要忘记小括号
      `
  2. 遍历对象: for…in…for…of…
for(var k in obj){   //k是属性名(在数组中是索引)
    console.log(obj[k]);   //得到的是属性值
    console.log(k);        
}

for(var a of arr){
   console.log(a);  //a是数组里的值
}

 var a=new Map([['tomcat',123],['lease',456],['sad',789]]);
 for(let i of a){
     console.log(typeof(i));   //结果为object
 }
  1. 内置对象:JS语言自带的对象

    • Math数学对象:不是构造函数,不需要new来调用,可以直接使用
      Math.PI:圆周率吧
      Math.abs( ):绝对值方法/隐式转换
      Math.max( )
      Math.floor( ):向下取整,往最小了取值
      Math.ceil( ):向上取整
      Math.round( ):四舍五入,.5特殊,往大了取
      Math.random( ):返回了一个随机的小数,方法内无参数,[ 0,1 )
    • Date( )日期对象,是一个构造函数,必须使用new
      ① 获取当前时间直接new;
      ② 返回参数内时间日期格式字符串new Date(‘2022-2-2 18:00:00’)或new Date(‘2022/2/2’);
      ③ getTime( ) 属性、valueOf( ) 属性、+Date( ) 和 Date.now( ) 获取到距离1970.1.1总的毫秒数。
    • Array数组对象,是一个构造函数
      var arr=new Array(2); //这个2表示数组的长度为2
      var arr=new Array(2,3); //等价于 [2,3]
  2. JSON
    是一个轻量级的数据交换格式,就是一个规范,能提升网络传输效率

格式:
     对象:{ } 
     数组:[  ]
     所有键值对都用  key: value
  //对象转换为json字符串
  var jsonu= JSON.stringify(user);
  
  //json字符串转化为对象, 参数为json字符串
  var obj = JSON.parse("{"name":"qingling","age":17}")

json 和 js 对象的区别:

var obj = {a:"hello", b:"hellob"};
var json = "{"a":"hello","b":"hellob"}"; 

 //注:json内部只能用双引号

你可能感兴趣的:(前端学习,javascript,前端)