QQ聊天记录中表情缓保存存在哪个文
702 2023-04-03 02:34:23
三部分组成:
推荐书籍:(阅读顺序-最上面的最重要)1.JavaScript高级程序设计2.ES63.你不知道的JavaScript4.JavaScript权威指南
【运行和输出】运行JS代码:浏览器或者NODE输出方式:alert/confirm/prompt/console.log/dir/table【数据类型详解和相互转换】数字:NaN/isNaN/parseInt/parseFloat……布尔:!/!!字符串:字符串拼接null/undefinedobject对象:键值对
谷歌浏览器的控制台(F12/Fn+F12)
按照相关的JS语法,去操作页面中的元素,有时还要操作浏览器里面的一些功能
变量:可变的量,就是一个名称,用来存储和代表不同值的东西多种定义方式:var / let / const / function / import / class
//1. ES3var a=12;//2. ES6--letlet b=1;b=2;//3. ES6--const:CONST创建的变量,存储的值不能被修改(可以理解为叫做常量)--其实是指针不能别修改const c=1; //=>undefinedc=2 //=>VM218:1 Uncaught TypeError: Assignment to constant variable.//4. 创建函数也相当于创建变量function fn(){}//5. 创建类也相当于创建变量class A{}//6. ES6的模块导入也可以创建变量import B from './B.js';//7. Symbol 创建唯一值let m=Symbol(100)let n=Symbol(100)m==n;//=> false
常用的缩写:
add/insert/create/new(新增)、update(修改)、delete/del/remove/rm(删除)、sel/select/query/get(查询)、info(信息)…4. 不能使用关键字和保留字当下有特殊含义的是关键字,未来可能会成为关键字的叫做保留字
代码强迫症(代码洁癖):良好的编程习惯、极客精神
-- 包含:常规数字、NaN
- NaN:not a number:不是一个数,但它属于数字类型 typeof NaN=>"number"
- NaN和任何值都不相等:NaN != NaN ,所以不能用相等的方式判断是否为有效数字
- isNaN:检测一个值是否为非有效数字,是返回true,反之是有效数字返回false
- isNaN([val])--在使用isNaN进行检测的时候,首先会验证检测的值是否为数字类型,如果不是,先基于Number()这个方法,把值转换为数字类型,然后再检测
-- 把其它类型的值转换为数字类型
== 进行比较的时候,可能要先把其它类型值转换为数字
== 比较的规律:1.对象 == 字符串 --> 对象转换为字符串2.null == undefined --> 这两者相等,但是和其它值都不相等3.剩下两边不同的都是转换为数字
只有0、NaN、空字符串''、null、undefined五个值转换为FALSE,其余都转换为TRUE(而且没有任何的特殊情况)
null and undefined都代表没有;
let num=null; //=>let num=0;一般最好用null作为初始的空值,因为零不是空值,它在栈内存中有自己的存储空间(占了位置)···num=12;
(种树时挖坑了但是没种树,这是0,null是连坑都没挖)2. undefined:意料之外(不是我能决定的)
let num;//=>创建一个变量没有赋值,默认值是undefinednum=12;
{[key]:[value],···}任何一个对象都是由零到多组键值对(属性名:属性值)组成的。(并且属性名不能重复)
=>对象.属性名=>对象[属性名] 属性名是数字或者字符串格式的=>如果当前属性名不存在,默认的属性值是undefined
1.1 属性名只能是数字或者字符串,创建的时候键值对之间为冒号,每一对键值对之间有逗号隔开
console.log(person.name); //name是具体的属性名 console.log(person['name']); //name是具体的属性名 console.log(person[name]); //代表name是一个变量 console.log(person['age']); console.log(person.sex);
1.2 当属性名是数字时双引号可以有也可以没有:obj['1'] & obj[1]是一样的
console.log(person[1]); console.log(person['1']);
1.3 如果属性名是数字,则不能使用点的方式获取属性值,会报错
console.log(person.1); //Uncaught SyntaxError: Unexpected number
1.4 对象的属性名虽然可以写成数字或者true等特殊格式,但是它们的数据类型都是字符串格式
let obj={ name:'cat', age:2, 1:100, 2:200, true:300 } for(var key in obj){ if(key==='true') continue;//会跳过 // if(key===true) continue;//不会跳过 console.log(key+'---'+obj[key]); }
属性名不能重复,如果属性名已经存在,不属于新增,属于修改属性值
person.GF='Lily'; person.name='Danny'; console.log(person.GF); console.log(person.name);
=>真删除:把属性彻底删除=>假删除:属性还在,值为空
//假删除 person.weight=null; console.log(person);//null //真删除 delete person.weight; console.log(person);//undefined
数组是特殊的对象1.我们中括号中设置的是属性值,它的属性名是默认生成的数字,从零开始递增,而且这个数字代表每一项的位置,我们把其称为“索引” => 从零开始,连续递增,代表每一项的数字属性名2.天生默认一个属性名length,存储数组的长度
let ary = [12,'aa',true,13]; console.log(ary); console.log(ary.length); console.log(ary['length']); console.log(ary[1]); //第一项索引0,最后一项索引ary.length-1; console.log(ary[ary.length-1]);//获取最后一项 let ary=[1,2,3,4]; console.dir(ary);/*Array(4)0: 11: 22: 33: 4length: 4__proto__: Array(0)ary={ 0:1, 1:2, 2:3, 3:4, length:4}数字作为索引(KEY属性名)length代表长度ary[0] 根据索引获取指定项的长度ary.length 获取数组的长度ary.length-1 最后一项的索引*/
扩展思考题:已知下面代码可以修改BOX元素的样式
box.style.color = 'red';
那么下面的写法是否可以写成修改元素的样式,如果不可以是为什么?
//第一种方案 let AA = box.style; AA.color = 'red'; //第二种方案 let BB = box.style.color; BB = 'red';
哪种方式可以实现,不能实现是因为什么?答:第一种可以实现,因为 element.style 是一个对象指针(引用数据类型的值),AA和box.style是同一个对象指针,所以当AA的值改变的时候,box.style的值也改变了。第二种 element.style.color 是一个具体的值,是字符串类型(基本数据类型),如果此时box.style.color的值是'pink',那么这个等式“let BB = box.style.color;”相当于“let BB = "pink";”
box.style.color = "pink";let BB = box.style.color;//=>let BB = "pink";BB = 'red';BB => 'red'box.style.color //=> 'pink';
通过document.getElementById方法获取的元素是对象数据类型的值
let box = document.getElementById('box'); console.log(typeof box);//=>'object' //基于.dir可以看到一个对象的详细信息 /* id:操作元素的ID值 className:操作元素的CLASS样式类的值 innerHTML:操作的元素的内容(可以识别标签) innerText:和innerHTML的区别是不能识别标签 tagName:获取元素的标签名(一般大写) …… style:操作元素的行内样式 属性值是一个新的对象CSSStyleDeclaration () */ console.dir(box)
函数就是一个方法或者一个功能体,函数就是把实现某个功能的代码放到一起进行分装,以后想操作实现这个功能,只需要把函数执行即可 => “封装”:减少页面中的冗余代码,提高代码重复使用率(低耦合高内聚)
function [函数名]([形参变量1],...){ //函数体:基于JS完成需要实现的功能 return [处理后的结果];}function fnName(){}
fnName();
创建函数分析:
function fn(){ var res = null; res =n+m; return res; }
赋值操作:第一步:创建右边的值;第二步:创建左边的变量;第三步:将值和变量关联在一起
var AA = fn(10,20);
等号右边一定是值,所以先把fn函数执行,再把执行后的返回结果和AA关联起来(函数的返回值只看return,有return后面返回值是什么就是什么,没有return就是undefined)
console.log(AA);
每一次函数执行的目的都是把函数体中的代码(先从字符串变为代码)执行=>形成一个全新的私有栈内存
fn(100,200)
函数每一次执行都会形成一个全新的私有栈内存(执行上下文),然后把函数代码从头到尾再执行一遍VO 和 AO阶段:JS编译过程涉及的概念。
首先关于整个生命周期,最重要的是要了解它的编译过程。发现有代码调用了一个函数在执行这个function之前,创建一个执行上下文(execution context),也可以叫执行环境。进入创建阶段(VO创建)a. 初始化作用域链(scope chain)b. 创建变量函数(variable object / VO)c. 创建参数对象(arguments object,传进来的参数),检查上下文,初始化其名字和值,以及建立引用对象的拷贝。d. 扫描上下文中的函数声明e. 为每一个扫描到的函数声明在VO中创建一个属性,命名为函数的名字,指向了存储空间中的对应函数。f. 如果函数名称已经存在了,这个引用指针将被重写为新的这一个。g. 扫描上下文中的变量声明h. 为每一个扫描到的变量声明在VO中创建一个属性,命名为变量的名字,初始化值为undefined。i. 如果变量名在内存中已经存在了,就跳过。j. 决定上下文中this的指向。执行阶段(VO => AO)a. 执行/解释上下文中的function,为变量赋值b. 代码按行执行就个人理解,他们的相应概念和包含内容如下。
scope :变量/函数起作用的区域scope chain : 保证对执行环境有权访问的所有变量和函数的有序访问。相当于VO + [scope]我们可以将作用域定义为一套规则,用来管理引擎如何在当前作用域以及嵌套的子作用域中根据标识符名称进行变量查找,作用域链是这套规则的具体实现。
execution context = {VO, this, [scope]}
this : 函数/方法的拥有者
第一个:基于typeof检测出来的结果:
局限性:
console.log(typeof 1);console.log(1);//控制台输出是有颜色的,黑色是字符串,蓝色是数字
面试题--"string" 字符串
console.log(typeof typeof typeof []);// typeof 检测出来的都是字符串,所以只要两个及以上同时检测,最后结果必然是“string”
第二个:js中的instanceof运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。某个实例 instanceof(从属于) 某个类,是就返回true,不是返回false
function Person(){};var p =new Person();console.log(p instanceof Person);//true
第三个:某个实例.constructor === 某构造函数
function employee(name, job, born) { this.name = name; this.job = job; this.born = born;}var bill = new employee("Bill Gates", "Engineer", 1985);console.log(bill.constructor === employee);//trueconsole.log(bill.constructor);//[Function: employee]/*输出:function employee(name, job, born){this.name = name; this.job = job; this.born = born;}*/
第四个:检测数据类型 Object.prototype.toString.call();
//1. 检测直接数据类型Object.prototype.toString.call();//=>"[object Undefined]"Object.prototype.toString.call();//=>"[object Undefined]"Object.prototype.toString.call([1,2]);//=>"[object Array]"Object.prototype.toString.call(null);//=>"[object Null]"Object.prototype.toString.call(undefined);//=>"[object Undefined]"Object.prototype.toString.call(12);//=>"[object Number]"Object.prototype.toString.call('aa');//=>"[object String]"Object.prototype.toString.call(true);//=>"[object Boolean]"Object.prototype.toString.call(NaN);//=>"[object Number]" //2. 检测引用数据类型 Object.prototype.toString.call({});//=>"[object Object]"Object.prototype.toString.call(/ /);//=>"[object RegExp]"Object.prototype.toString.call(Math);//=>"[object Math]"Object.prototype.toString.call(Date);//=>"[object Function]"function fn(){}Object.prototype.toString.call(fn);//=>"[object Function]"
判断--条件成立做什么?不成立做什么?
if(条件){ 条件成立执行 }else if(条件2){ 条件2成立执行 }…… else{ 以上条件都不成立执行 }
==: 相等 (如果左右两边数据值类型不同,是默认先转换为相同的类型,然后比较)'5' == 5; =>TRUE===:绝对相等(如果类型不一样,肯定不相等,不会默认转换数据类型)'5' === 5 ;=> FASLSE
项目中为了保证业务的严禁,推荐使用 ===
循环--重复做某些事情就是循环
函数的参数是一个内部的对象arguments返回值
循环迭代对象的属性名语法: for(var 变量(key) in 对象){}对象中有多少组键值对,就循环执行几次(除非break结束)
var obj = { name: 'dog', age: 3, friends: 'Lily,Danny', 1: 100, 2: 120, 3: 150}//每一次循环key变量存储的:当前对象的属性名//获取属性名:obj[属性名] = obj[key] //obj.key / obj['key']这样写不行,因为obj对象中没有属性名为key的for (var key in obj) { console.log('属性名:' + key + '--' + '属性值:' + obj[key])}//for in在遍历的时候优先循环数字属性名(从小到大)/*输出如下:属性名:1--属性值:100属性名:2--属性值:120属性名:3--属性值:150属性名:name--属性值:dog属性名:age--属性值:3属性名:friends--属性值:Lily,Danny*/
const array1 = ['a', 'b', 'c'];for (const element of array1) { console.log(element);}/*'a' 'b''c'*/