unicode编码,以下是一些特殊的字符编码
》0表示结束
》10表示换行
》13表示回车
》32表示空格
》33到47表示标点
》48到57表示0到10
》65到90表示大写字母
》97到122表示小写字母
》127表示删除键
基本的计算机常识:
1》8位一字节,存储数字,大小写字母,2的8次方是128
2》16位两字节,2的16次方是65536。使用GB2312:增加收录了6000多个汉字,还有其他的一些西文字母和日文假名。
用0000~FFFF来表示汉字
1个16进制数刚好是4个0/1位。FFFF是4x4=16位。
8位一字节,16位两字节,16位表示汉字。
3》24位三字节,2的17次方是131072
编码:utf-8编码是变长存储。最少可以使用1个字节。
unicode编码的缺点是:两个字节不够用,每个字符需要三个字节
数字1和字符1的区别:》功能不同,字符只能相加;数字可以进行多种计算
》存储形式不同,数字是变成二进制直接存储;而字符是要先经过编码变成数字后,再进行存储。如字符1的编码是49,二进制即00110001。所以最后数字1存的就是1,字符1存的就是49。这些转换为二进制再去存储在计算机中。
这里就有一个问题,既然字符串存的也是数字,那么计算机如何区分存的是数字还是字符串呢?答案是计算机根据文件格式判断。
js七种数据类型:(四基两空一对象)
number
string
bool(只有两个值:true和false)
symbol
null
undefined
object(数组 函数 日期不是数据类型,也是对象,而且是特殊的对象)
number数字类型:
正0 负0
无穷大:infinity -infinity +infinity
无法表示的数字:NaN (Not a Number) 但它是一个数字 NaN === NaN 结果是false
JS数字是以64位浮点数的形式去存储的。64位存储一个number,符号占1位,指数占11位(-1023 ~ 1024),有效数字占52位(开头的1省略)。
范围和精度:
范围(忽略符号位):
指数拉满,有效数字拉满,得到最大二进制数字;
Number.MAX_VALUE:1.7976931348623157e+308;
指数负方向拉满、有效数字最小1,得到最小值
Number.MIN_VALUE:5e-324
精度(有效数字):
最多只能到52+1个二进制位表示有效数字,2的53次方对应的十进制是9后面15个零,所以15位有效数字都能精确表示,16位有效数字如果小于90开头,也能精确表示,9110000000000001就存不下来。
字符串String(每个字符两个字节,阉割版的utf-8):
字符串的写法:单引号 双引号 反引号 ;这里要注意的是引号不属于字符串的一部分,如果要写的字符串里要包含一些特殊字符,需要用到转义符。如it's ok这个字符串
let obj = 'it's ok';这样写的话,JS引擎会认为'it'就结束了。
正确写法1:let obj = 'it's ok'
正确写法2:let obj = "it's ok"
正确写法3: let obj = `it's ok`
表示转义,'表示' "表示" n表示换行 r表示回车 t表示tab制表符 表示
uFFFF表示对应的Unicode字符(16进制)xFF表示前256个Unicode字符(16进制)这两种方式都是直接用Unicode编码去表示字符了。如数字1的Unicode编码是49,所以x31就表示数字1。(16进制的31就是10进制的49)。u4F60就是汉字'你'。(Unicode表示,utf-8存储)
之前在字符串中,多行字符串是不行的,即不能直接回车,想要回车需要使用转义符。但是在用反单引号的时候,可以直接回车,如图:
【字符串的属性,其实只有对象有属性。其他六种基本数据类型都是没有属性的。这个地方以后再做解释。数组 函数 日期是特殊的对象。只有函数有返回值。】
字符串的长度,str.length
通过下标读取字符,str[index]: let s = "hello";console.log(s[0]); //会打印出"h";注意index是从0开始,s[0]是第一个字符;注意index到length:let s = "hello";console.log(s[5]);//会打印undefined,不报错
base64转码:window.btoa正常字符串转为Base64编码的字符串。window.atobBase64编码的字符串转为原来的字符串。
bool布尔(就两个值,true和false)
下列的运算符会得到bool值
1》否定运算 !value 2》相等运算 1==2 1!=2 3===4 3!==4 3》比较运算 1>2
这里要注意5个falsy值:null undefined 0 NaN ''
注意一下null和undefined两个空值的区别:其实没有本质区别。
1》如果一个变量声明了,没有赋值,那么js默认它的值是undefined,而不是null
2》如果一个函数,没有写return,那么默认return undefined,而不是null
3》前端程序员习惯上,把非对象的空值写为undefined,把对象的空值写为null。但这仅仅是习惯而已
符号symbol类型都没怎么用。就不介绍了。
变量声明
1》var a = 1
2》let a = 1
3》const a = 1
4》a = 1
区别:var是过时的,不好用的,还会涉及到变量提升,就近原则等问题,var声明的全局变量会变成window的属性。let是新的,更合理的方式。const是声明的时候必须赋值,且不能再改。最后这种声明方式,不要用!!!
let声明的规则:遵循块作用域,即作用范围不能超出{};在同一块作用域中,不能重复申明;可以给其赋值,也可以不赋值,不赋值,默认就是undefined;必须先声明后使用,否则报错;全局声明的let变量,不会变成window的属性,但var就会;for循环配合let有奇效(这里要联系for循环变量从1到5,setTimeout函数打印该变量的值,如果该变量是用var声明的,则最后会打印出5个5,但若是let声明的,会打印出12345!!!)。
变量声明,指定值,同时也就指定了类型,但是值和类型都可以随意变化。
name和'name'的区别:
前者只有在 var name 或者let name之后,才有意义,是个变量。而后者就是个字符串常量。
类型转换
js提供了一些函数强制进行数据类型转换,也会在有些操作中就进行数据类型转换。比如运算符+。
number-》string String()即可。但一般有更简单的写法,将变量加上一个空字符串
string-》number Number()即可。但一般直接减去0,也可以直接在变量前加一个+号。另还有parseInt()(现在使用该函数,可以不用指定其进制,默认都是10进制。之前如字符串以0开头,会将其按8进制的计算去转换)。
JS的bug:
使用String函数转化的时候:
注意其他类型和bool类型的转换,和字符类型的转换,在这里也有bug存在。1.toString()是不合法的。(1).toString和1..toString()就对了。因为1.toString(),当读到.的时候,默认它是个小数,后面还要跟数字,所以就报错。但加了括号就隔开。多加个.是把小数点后面的0省掉了。
JS 的 number 全都是以小数(浮点数)的形式存储的,没有单独的整数。
JS对象object
对象的语法:
定义>对象是无序的键值对的集合。
写法>1 let obj = {name:'fa'};
2 let obj = new Object({name:'fa'});
3 console.log({name:'fa'});匿名对象
细节>对象的属性也就是键名,是字符串,不是标识符,可以包含任意字符。(之前说过,标识符不能以数字开头)。就算键名的引号省略了,它仍是字符串。
若想用变量表示对象的属性,要用中括号,如下图
另外还有一些奇怪的属性名,如下图:
对象的隐藏属性:
隐藏属性:JS中每一个对象都有一个隐藏属性__proto__;
这个隐藏属性储存着其共有属性组成的对象的地址
这个共有属性组成的对象叫做原型
所以也就是说,隐藏属性储存着原型的地址
对象的操作:增删改查
删属性:deleteobj.xxx 或 delete obj['xxx']。
不可直接删除一个对象,即delete obj是错误的。返回值是false。
delete一个对象不存在的属性也不会报错。
打印出一个对象不存在的属性的值,也不会报错,就是undefined。
注意属性值为undefined和属性值为''即空字符串的区别。
想要判断对象中是否包括这个属性,使用in语法。'xxx' in obj,结果为true就是存在,false就是不存在。
注意:obj.xxx === undefined并不能判断该属性xxx不在obj对象中。因为也有可能obj有xxx这个属性,不过值是undefined。改进:'xxx' in obj && obj.xxx === undefined,若一个对象确实有属性xxx,且值是undefined,上面这个结果为true。如图:
读属性:
查看对象obj的自身属性Object.keys(obj)
查看对象obj的自身以及共有属性:console.dir(obj)
查看对象obj的属性值Object.values(obj)
查看对象obj的属性以及对应的属性值Object.entries(obj)
如果想显示对象obj的共有属性,可以用console.dir(obj)即可。在chrome中,共有属性就是隐藏属性,名字是__proto_。所以可以直接通过写obj.__proto_去查看它的共有也就是隐藏属性。但是不推荐这种写法!!!因为这个__proto_是隐藏的,而且不同的浏览器可能命名也不相同。【因为我们说过这个obj.__proto__是对象,所以尝试用console.dir的方法去打印这个对象,即原型的自身属性,如下图】
判断一个属性是自身的还是共有的,obj.hasOwnProperty() true就是自身属性,false不是。
'name' in obj和obj.hasOwnProperty('name') 的区别
'name' in obj 查看属性name是否在obj里。
hasOwnProperty() 方法判断对象的属性是自身的还是共有的。此方法不会检查对象原型链中的属性;该属性必须是对象本身的一个成员。
查看属性:obj.xxx obj['xxx'] 优先使用中括号写法 如果写一个该对象没有的属性,不会报错,会显示undefined。另外默认每一个window的name属性都是空字符串。如图:
写属性,即修改或者增加:
直接赋值:let obj = {age:18};
obj.name='fa';等价于 obj['name']='fa'
批量赋值:Object.assign(obj,{add:'hn'})
无法通过自身修改或者增加共有属性,例:
let obj = {},obj2 = {};//共有属性toString
obj.toString = 'xxx';//只会改obj自身属性
obj2.toString还是在原型上
如果非要修改或者增加原型上的属性(即共有属性)
obj.__proto__.toString = 'xxx'
Object.prototype.toString = 'xxx'
上面两句话是等价的,因为obj.__proto__ === Object.prototype是为真的【用内存图就可以看出】
若将obj.__proto__ = null,即将该对象的原型置为空,那么obj就会变成一个纯净的对象,不再有公有属性,如下图:
红线标注的地方是chrome浏览器在欺骗你,这根本不是一个对象,
将原型置为null后,
一般来说,不要修改原型,会引来很多问题。所以在修改隐藏属性的时候,不推荐使用__proto_,推荐使用Object.create。例:
let common = {kind:'human'}
let obj = {name:'ff'}
let obj2 = {name:'jack'}
obj.__proto__ = common
obj2.__proto__ = common
即改写为:
let common = {kind:'human'}
let obj = Object.create(common)
obj.name = 'ff'
let obj2 =Object.create(common,{name:{value:'jack'}}
这种写法意思就是要改隐藏属性,那么在一开始创建的时候就改
原型:
每个对象都有原型(原型里存着对象的共有属性)(比如obj的原型就是一个对象) (obj.__proto__存着这个对象的地址,这个对象里有toString/constructor/valueOf等属性。)
对象的原型还是对象,所以对象的原型也有原型。var obj = {}的原型即为所有对象的原型。这个原型包含所有对象的共有属性,是对象的根。这个原型因为也是对象,所以也有原型,但是是null。
比如:var obj = new Object();obj的原型obj.__proto__就是一个对象,obj.__proto_存着这个对象的地址,这个对象里有toString/constructor/valueOf等属性。并且obj的原型即为所有对象的原型。这个原型包含所有对象的共有属性,是对象的根。这个原型也有原型,是null。注意理解这段话。
画内存图解释一下:
Object.create()和new Object()的区别:前者是为新创建的对象指定原型,后者是创建对象及其属性,如图:
对象的key在内存中是如何存储的:如何存储,要看它是什么数据类型。如果是对象,就需要再开辟一块内存存放;如果是其他的基本数据类型,因为是定长的,就直接按顺序放。
原型和共有属性:原型是共有属性的集合组成的对象。共有属性依附于原型这个对象上。
画内存图好好理解一下:
继续加油鸭。不忘初心,努力,希望,等待 ,坚持。相信自己!!!