变量和类型
- Javascript规定了几种语言类型
数据类型一般分为七种:Number String Boolean null undefined Object Symbol
基本类型:Number String Boolean null undefined
引用类型:Object Date Array RegExp Function
String:并非字符串,而是字符串的UTF16编码
Number:
Boolean:true、false//加法运算中有+0和-0,但是除法中要区分,区别+0和-0的方式为 console.log(1/+0) //Infinity console.log(1/-0) //-Infinity console.log( 0.1 + 0.2 == 0.3);//false //首先声明这不是bug,原因在与十进制到二进制的转换导致的精度问题! //正确的比较方法 console.log( Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON);//true console.log( 0.1*10 + 0.2*10 == 0.3*10) //true
Object:
null:表示不存在的对象,是关键字1.JavaScript对象的定义是“属性的集合”。属性分为数据属性和访问器属性,二者都是 key-value 结构,key可以是字符串或者Symbol类型。 2.JavaScript的“类”仅仅是运行时对象的一个私有属性,而JavaScript中是无法自定义类型的。 3.Number、String 和 Boolean,三个构造器是两用的,当跟 new 搭配时,它们产生对象,当直接调用时,它们表示强制类型转换。 4.Symbol 函数比较特殊,直接用 new 调用它会抛出错误,但它仍然是Symbol对象的构造器。 我们在原型上添加方法,都可以应用于基本类型。 问题:为什么给对象添加的方法能用在基本类型上? 答案:运算符提供了装箱操作,它会根据基础类型构造一个临时对象,使得能够在基础类型上调用对应对象的方法。
undefined:是一个变量,而非关键字,表示有值但是未定义,任何变量赋值前都是undefined
Symbol:表示独一无二的值,是非字符串的对象key的集合。Symbol值通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种就是字符串,另一种就是新增的Symbol类型。饭是属性名属于Symbol类型,就是独一无二的,可以保证不会与其它属性名产生冲突console.log(Symbol() === Symbol()); // false console.log(Symbol("Alice") === Symbol("Alice")); // false //Symbol值不能与其他类型的值进行运算 console.log(Symbol('Alice') + "Bruce"); // 报错 //Symbol值可以显式转为字符串,也可以转为布尔值,但是不能转为数值 var symbol = Symbol("Alice"); console.log(symbol.toString()); // 输出:Symbol(Alice) console.log(Boolean(symbol)); // 输出:Symbol(Alice) if (symbol) { console.log("YES"); // 输出:Yes } console.log(Number(symbol)); // 报错:TypeError
- 理解值类型和引用类型
值类型:String Number Boolean null undifined
引用类型:Array Date Object RegExp Function
区别一:
存储位置不一样:值类型的变量会保存在栈内存中,如果在一个函数中声明一个值类型的变量,那么这个变量当函数执行结束后会自动销毁;引用类型的变量名会保存在栈内存中,但是变量值会存储在堆内存中,引用类型的变量不会自动销毁,当没有引用变量引用他时,系统的垃圾回收机制会回收他。
区别二:栈内存 堆内存 a=10 arr [1,2,3]
复制方式不一样:值类型的变量直接复制就是深复制,比如var a = 10; var b = a; b = 20; console.log(a) //10;引用类型的变量直接赋值实际上是传递引用,只是浅复制
区别三:
值类型无法添加属性和方法,引用类型可以添加属性和方法
区别四:
值类型的比较和引用类型的比较:值类型的比较是值的比较,只要值相等他们就相等;引用类型的比较是值和引用地址的比较,值和引用地址都相等才相等。(注意==和===,==在比较时做了类型转换,转换成相同类型之后比较值;而===是比较值和类型) -
javascript八大数据结构
详情连接:https://blog.youkuaiyun.com/yeyazhishang/article/details/82353846 -
javascript中变量在内存中的储存方式
变量:
可分为整形、浮点型、字符型、指针型,其值在其作用域内可以改变的量叫做变量。变量在其使用前必须定义,每一个变量都有自己的地址。js提供了parseInt()和parseFloat()两个转换函数,前者把值转换为整数,后者把值转换为浮点数。
??? -
判断数据类型的方式
① typeof:可以对基本类型做出准确判断,但对于引用类型,用他就有点力不从心了typeof 返回一个表示数据类型的字符串,返回结果包括:number、boolean、string、object、undefined、function等6种数据类型。
typeof 可以对JS基本数据类型做出准确的判断(除了null),而对于引用类型返回的基本上都是object, 其实返回object也没有错,因为所有对象的原型链最终都指向了Object,Object是所有对象的`祖宗`。 但当我们需要知道某个对象的具体类型时,typeof 就显得有些力不从心了。
② instanceof:判断对象和构造函数在原型链上是否有关系,如果有关系,返回真,否则返回假function Aaa(){} var a1 = new Aaa(); alert( a1 instanceof Aaa); //true判断a1和Aaa是否在同一个原型链上,是的话返回真,否则返回假 var arr = []; alert( arr instanceof Aaa);//false
var str = 'hello'; alert(str instanceof String);//false var bool = true; alert(bool instanceof Boolean);//false var num = 123; alert(num instanceof Number);//false var nul = null; alert(nul instanceof Object);//false var und = undefined; alert(und instanceof Object);//false var oDate = new Date(); alert(oDate instanceof Date);//true var json = {}; alert(json instanceof Object);//true var arr = []; alert(arr instanceof Array);//true var reg = /a/; alert(reg instanceof RegExp);//true var fun = function(){}; alert(fun instanceof Function);//true var error = new Error(); alert(error instanceof Error);//true
从上面的运行结果我们可以看到,基本数据类型是没有检测出他们的类型,但是我们使用下面的方式创建num、str、boolean,是可以检测出类型的:
var num = new Number(123); var str = new String('abcdef'); var boolean = new Boolean(true);
③ constructor:查看对象对应的构造函数
var str = 'hello'; alert(str.constructor == String);//true var bool = true; alert(bool.constructor == Boolean);//true var num = 123; alert(num.constructor ==Number);//true var nul = null; alert(nul.constructor == Object);//报错 var und = undefined; alert(und.constructor == Object);//报错 var oDate = new Date(); alert(oDate.constructor == Date);//true var json = {}; alert(json.constructor == Object);//true var arr = []; alert(arr.constructor == Array);//true var reg = /a/; alert(reg.constructor == RegExp);//true var fun = function(){}; alert(fun.constructor ==Function);//true var error = new Error(); alert(error.constructor == Error);//true
从上面的测试中我们可以看到,undefined和null是不能够判断出类型的,并且会报错。因为null和undefined是无效的对象,因此是不会有constructor存在的。
同时我们也需要注意到的是:使用constructor是不保险的,因为constructor属性是可以被修改的,会导致检测出的结果不正确:function Aaa(){} Aaa.prototype.constructor = Aaa;//程序可以自动添加,当我们写个构造函数的时候,程序会自动添加这句代码 function BBB(){} Aaa.prototype.constructor = BBB;//此时我们就修改了Aaa构造函数的指向问题 alert(Aaa.construtor==Aaa);//false
④ Object.prototype.toString
toString是Object原型对象上的一个方法,该方法默认返回其调用者的具体类型,更严格的讲,是 toString运行时this指向的对象类型, 返回的类型。基本上所有对象的类型都可以通过这个方法获取到。var str = 'hello'; console.log(Object.prototype.toString.call(str));//[object String] var bool = true; console.log(Object.prototype.toString.call(bool))//[object Boolean] var num = 123; console.log(Object.prototype.toString.call(num));//[object Number] var nul = null; console.log(Object.prototype.toString.call(nul));//[object Null] var und = undefined; console.log(Object.prototype.toString.call(und));//[object Undefined] var oDate = new Date(); console.log(Object.prototype.toString.call(oDate));//[object Date] var json = {}; console.log(Object.prototype.toString.call(json));//[object Object] var arr = []; console.log(Object.prototype.toString.call(arr));//[object Array] var reg = /a/; console.log(Object.prototype.toString.call(reg));//[object RegExp] var fun = function(){}; console.log(Object.prototype.toString.call(fun));//[object Function] var error = new Error(); console.log(Object.prototype.toString.call(error));//[object Error]
从这个结果也可以看出,不管是什么类型的,Object.prototype.toString.call();都可以判断出其具体的类型。
⑤ 下四种方法各自的优缺点
不同类型的优缺点 typeof instanceof constructor Object.prototype.toString.call() 优点 使用简单 能检测出引用类型 基本能检测所有的类型(除了null和undefined) 检测出所有的类型 缺点 只能检测出基本类型(除null) 不能检测基本类型,且不能跨iframe constructor易被修改,也不能跨iframe IE6下,undefined和null均为Object
原型和原型链
- 几种继承方式及他们的优缺点
https://blog.youkuaiyun.com/caijixin/article/details/78295676
- new一个对象的详细过程,手动实现一个new操作符
系统会在内部创建一个this对象,将__proto__转到构造函数的prototype上面,最后再隐式的把this对象return出来,所以person就是一个this对象。function Person() { var this = { __proto__: Person.prototype } this.name = name this.age = age return this } var person = new Person()
- 理解词法作用域和动态作用域
词法作用域:也就是静态作用域
动态作用域:function foo(){ console.log(a);//2 } function bar(){ var a=3; foo(); } var a=2; bar();
主要区别:function foo(){ console.log(a);//3(而不是2!) } function bar(){ var a=3; foo(); } var a=2; bar();
词法作用域是在写代码或者说定义时确定的,而动态作用域是在运行时确定的。
词法作用域关注函数在何处声明,而动态作用域关注函数从何处调用。
作用域和闭包
- javascript的作用域
在ES5中,没有块级作用域,JS的作用域分为函数作用域和全局作用域两种。
在ES6中,新增了let和const,这两个类型的变量只存在于块级作用域中,并且不存在变量提升。 - 闭包的作用
①可以读取自身函数外部的变量
②让这些外部变量始终保存在内存中 - this
①ES5,this是在函数调用时被绑定的,它指向哪里取决于在哪里被调用
②
执行机制
- 312312
语法和API