我的前端知识梳理-ES5篇

本篇文章记录自己对es5知识点的理解

原文链接

1 JS创建对象的方式

es5有三种方式创建对象,分别是

// 第一种方式,字面量var
o1 = {name: “o1”}var
o2 = new Object({name: “o2”})// 第二种方式,通过构造函数var
M = function(name){ this.name = name }var
o3 = new M(“o3”)// 第三种方式,Object.createvar p = {name: “p”}var
o4 = Object.create§ 对于对象,在这里也不做赘述,这里解释一下js中什么是标识符
/*

标识符

  • 在JS中所有的可以由我们自主命名的都可以称为是标识符

  • 例如:变量名、函数名、属性名都属于标识符

  • 命名一个标识符时需要遵守如下的规则:

1.标识符中可以含有字母 、数字 、下划线_ 、$符号

2.标识符不能以数字开头

3.标识符不能是ES中的关键字或保留字

4.标识符一般都采用驼峰命名法

  • JS底层保存标识符时实际上是采用的Unicode编码,

所以理论上讲,所有的utf-8中含有的内容都可以作为标识符

*/

这里就看出js的缺陷了,如果对象中的属性不符合标识符规范怎么办,也就是我用.操作符无法获取属性的时候,比如说 var obj={ 1 : 1 } console.log(obj.1)

事实上我们是无法通过点操作符来获取这个属性的,这里我们只能用var obj={ ‘1’:1 } 来声明对象,那该如何获取属性呢,js为我们提供了一个类似数组索引 [ ] 的方式来获取对象

如上面的 var obj={name:’张三’}

我们可以用obj.name 或者 obj[‘name’] 这两种方式来获取 但是var obj={ ‘1’:1 } 只能用obj[‘1’]来获取这个属性值

那这两种有什区别呢

. 运算符:右侧必须是一个属性名称命名的简单标识符,如.name

[]:右侧必须是一个计算结果为字符串的表达式

那既然[]是一个计算结果为字符串的表达式,那就给[]赋予了强大的功能,如字符串拼接,三目运算符等

let obj={‘1’:123, name:‘张三’}
console.log(obj[‘1’],obj.name,obj[‘name’]) // 输出 123 “张三” “张三”

2 =====的区别

不同于Java中的比较,js有这两种比较的方式,但他们有什么区别呢

简单来说: == 代表相同, ===代表严格相同, 为啥这么说呢

这么理解: 当进行双等号比较时候: 先检查两个操作数数据类型,如果相同, 则进行===比较, 如果不同, 则愿意为你进行一次类型转换, 转换成相同类型后再进行比较, 而===比较时, 如果类型不同,直接就是false.

比较过程:

双等号==:

(1)如果两个值类型相同,再进行三个等号(===)的比较

(2)如果两个值类型不同,也有可能相等,需根据以下规则进行类型转换在比较:

1)如果一个是null,一个是undefined,那么相等

2)如果一个是字符串,一个是数值,把字符串转换成数值之后再进行比较

三等号===:

(1)如果类型不同,就一定不相等

(2)如果两个都是数值,并且是同一个值,那么相等;如果其中至少一个是NaN,那么不相等。(判断一个值是否是NaN,只能使用isNaN( ) 来判断)

(3)如果两个都是字符串,每个位置的字符都一样,那么相等,否则不相等。

(4)如果两个值都是true,或是false,那么相等

(5)如果两个值都引用同一个对象或是函数,那么相等,否则不相等

(6)如果两个值都是null,或是undefined,那么相等

那什么时候用==什么时候用===呢,我个人认为的是

只有在判断obj.a==null的时候使用双等,等同于obj.a===undefind||obj.a===null

其他一律使用===(三等号)因为我们通常在判断是否相等的时候首先就得确定两遍的类型

3 为什么 0.1 + 0.2 != 0.3

先来看一个现象,那么为什么会出现这种情况呢

因为 JS 采用 IEEE 754 双精度版本(64位),并且只要采用 IEEE 754 的语言都有该问题。

我们都知道计算机表示十进制是采用二进制表示的,所以 0.1 在二进制表示为

// (0011) 表示循环

0.1 = 2^-4 * 1.10011(0011)

这个问题简单来说是底层在表示0.1和0.2的时候采用的是二进制,在采用这个双精度版本时,二进制相加后再转换为十进制的时候就会得到结果是不等于0.3的

那么我们实际编码时如果遇到这种情况该怎么判断呢

原生的解决办法如下

parseFloat((0.1 + 0.2).toFixed(10))或者转换成整数计算后再转换成小数

4 什么是原型和原型链
每个函数都有 prototype 属性,除了 Function.prototype.bind(),该属性指向原型。

每个对象都有 proto 属性,指向了创建该对象的构造函数的原型。其实这个属性指向了 [[prototype]],但是 [[prototype]] 是内部属性,我们并不能访问到,所以使用 proto 来访问。

对象可以通过 proto 来寻找不属于该对象的属性,proto 将对象连接起来组成了原型链。

构造函数

function Foo(name,age){
    this.name = name;
    this.age = age;
    //return this;默认有这一行
}
var f = new Foo('zhangshan',20);
//1.创建了一个新对象
//2.将this指向这个新对象
//3.执行构造函数里面的代码
//4.返回新对象(this)

var a={} //其实是var a = new Object()语法糖
var a=[] //其实是var a = new Array()语法糖
function Foo(){} // 其实是var Foo = new Function()

// 使用instanceof判断一个函数是否是一个变量的构造函数
// f instanceof Foo  ==> true
// f.__proto__一层层往上寻找能否查询到Foo.prototype
// f instanceof Object  ==> true

原型的规则和示例

// 1.所有的引用类型(数组,对象,函数),都具有对象特性,即可以自由扩展属性(null除外)  
    var obj={};obj.a=100;
    var arr={};arr.a=100;
    function fn(){} 
    fn.a=100;
// 2.所有的引用类型(数组,对象,函数),都有一个__proto__(隐式原型)属性,属性值是一个普通的对象
    console.log(obj.__proto__);
    console.log(arr.__proto__);
    console.log(fn.__proto__);
// 3.所有的函数,都有一个prototype属性(显式原型),属性值是一个普通的对象
    console.log(fn.prototype);
// 4.所有的引用类型(数组,对象,函数),__proto__属性指向它的构造函数的prototype属性值
    console.log(obj.__proto__===Object.prototype);
// 5.当视图得到一个对象的某个属性的时候,如果这个对象本身没有这个属性,那么
去它的__proto__(即它的构造函数prototype)中去找
    function Foo(name,age){
        this.name = name;
    }
    Foo.prototype.alertName = function(){
        alert(this.name);
    }
    //创建实例
    var f = new Foo('zhangsan');
    f.printName = function(){
        console.log(this.name);
    }
    f.printName();//可以获取到printName这个属性直接获取
    f.alertName();//获取不到alertName属性这是去找他的构造函数的prototype中去找

原型链

var f = new Foo('zhangsan');
f.toString();

分析:

1.首先去自身的属性中去找toString方法,没有则去隐式原型__proto__去找

2.__proto__指向其构造函数的显式原型Foo.prototype,如没找到再去Foo.prototype的隐式原型去找

3.Foo.prototype的__proto__又指向Object.prototype显式原型,然后再寻找其隐式原型__proto__即查询到toString方法,这就是原型链

总结

Object 是所有对象的爸爸,所有对象都可以通过 proto 找到它 Function 是所有函数的爸爸,所有函数都可以通过 proto 找到它 Function.prototype 和 Object.prototype 是两个特殊的对象,他们由引擎来创建 除了以上两个特殊对象,其他对象都是通过构造器 new 出来的 函数的 prototype 是一个对象,也就是原型 对象的 proto 指向原型, proto 将对象和原型连接起来组成了原型链

5 什么是作用域和闭包
作用域和闭包是一个老生常谈的问题,经常会出现在各大面试中。下面就来简单介绍一下,

执行上下文

// 示例代码:
    console.log(a);//undefined
    var a=100;
    fn('zhangsan');// zhangsan 20
    function fn(name){
        age=20;
        console.log(name,age);
        var age;
    }
// 解释:
// 范围 | 一段
                    
                    

你可能感兴趣的:(我的前端知识梳理-ES5篇)