美文网首页
2020-12-22

2020-12-22

作者: 豆_6b8c | 来源:发表于2020-12-22 17:11 被阅读0次

进阶篇

一、javascript

1、内置类型

·js中分为7种内置类型,7种又分为两大类型:基本类型和对象

·基本类型有六种:null、undefined、boolean、number、string、symbol

·其中js的数字类型是浮点类型的,没有整型。并且浮点类型基于\color{#ea4335}{IEEE} \color{#ea4335}{754}标准实现,在使用中会遇到某些bug,\color{#ea4335}{NAN}也属于number类型,并且\color{#ea4335}{NAN}不等于自身
·对于基本类型来说,如果使用字面量的方式,那么这个变量只是个字面量,只有在必要的时候才转换为对应的类型

let a=111 //这只是字面量,不是number类型
a.toString() //使用时候才会转为对象类型

| 对象(object)是引用类型,在使用过程中会遇到浅拷贝和深拷贝的问题

let a= {name:'FE'}
let b= a
b.name= 'EF'
console.log(a.name)

2、Typeof

| typeof对于基本类型,除了\color{#ea4335}{null}都可以显示正确的类型

typeof 1 // 'number'
typeof '1'  // 'string'
typeof true  // 'boolean'
typeof Symbol() // 'symbol'
typeof b // 'undefined' b没有声明,但是还是会显示undefined ,typeof返回的数据类型都是string

| typeof对于对象,除了函数都会显示object

typeof [] // 'object'
typeof {} // 'object'
typeof console.log // 'function'

| 对于null来说,虽然他是基本类型,但是会显示object,这是一个存在很久了的bug

typeof null // 'object'

| ps:为什么会出现这种情况呢?因为在JS的最初版本中,使用的是32位系统,为了性能考虑使用低位存储了变量的类型信息,000开头代表是对象,然而null表示全为零,所以将它错误的判断为object。虽然现在的内部判断代码已经改变了,但是对于这个Bug却是一直流传下来

如果我们想获得一个变量的正确类型,可以通过Object.prototype.toString.call(xx).这样我们就可以获得类似[object type]的字符串

let a
//我们也可以这样判断undefined
a===undefined
//但是undefined不是保留字,能够在低版本浏览器被赋值
let undefined=1
//这样判断就会出错
//所以可以用下面的这种方式来判断,并且代码量更少
//因为void后面随便跟上一组成表达式
//返回就是undefined
a===void 0

3、类型转换

转Boolean
| 在条件判断时,除了undefined,null,false,NaN,‘’,0,-0,其他所有值都转为true,包括所有对象
对象转基本类型
| 对象在转换基本类型时,首先会调用valueOf 然后调用toString,并且这两个方法你是可以重写的

let   a={
    valueOf(){
        return 0
    }
}

四则运算

只有当假发运算时,其中一方是字符串,就会把另一个也转为字符串类型。其他运算只要其中一方是数字,那么另一方就转为数字。并且加法运算会触发三种类型转换;将值转换为原始值,转换为数字,转换为字符串

1  +  '1'     //'11'
2  * ' 2'     //4
[1,  2]+  [2, 1]  //1,22,1
// [1,2].toString() ->'1,2'
// [2,1].toString() ->'2,1'
// '1,2'  + '2,1' = '1,22,1'

| 对于加号需要注意这个表达式 ‘a'++'b'

'a' ++'b' //->"aNaN"
//因为 ++'b'    -> NaN
//你也许在一些代码中见过 + '1' ->1

=== 操作符
| 这里来解析一道题目 [] ==![] // ->true下面是这个表达式为何为true的步骤

// []转成true,然后取反变成false
[]==false
[]==ToNumber(false)
[]==0

4、原型

每个函数都有prototype属性,除了Function.prototype.bind(),该属性指向原型。
每个对象都有prooto属性,指向了创建该对象的构造函数的原型,其实这个属性指向了[[prototype]],但是[[prototype]]是内部属性,我们并不能访问到,所以使用proto来访问。
对象可以通过proto来寻找不属于该对象的属性,proto将对象连接起来组成了原型链。

5、new

| 要手动实现一个new操作符,首先要知道new操作符都做了什么事,即
1.创建一个新对象
2.链接到原型(将构造函数的prototype赋值给新对象的proto);
3.绑定this(构造函数中的this指向新对象并且调用构造函数)
4.返回新对象
这样我们就可以手动实现一个new方法了
| 在调用new的过程中会发生以上四件事情,我们也可以试着来自己实现一个

function createNew(){
//创建一个新对象
let obj = {}
//获得构造函数
let Con = [].shift.call(arguments)
//链接到原型(给obj这个新生对象的原型指向它的构造函数的原型)
obj.__proto__ = Con.prototype
//绑定this,执行构造函数
let result = Con.apply(obj,arguments)
//确保new出来的是个对象
return typeof result === 'object' ? result:obj
}

我们实现的createNew()方法需要传入的参数是:构造函数+属性
首先我们创建一个新对象,
然后通过arguments类数组我们可以知道参数中包含了构造函数以及我们调用createNew时传入的其他参数,接下来就是要想如何得到这个构造函数和其他的参数,由于arguments是类数组,没有直接的方法可以供其使用,我们可以有以下两种方法

1.Array.from(arguments).shift();转换成数组 使数组的方法shift将第一项弹出

2.[].shfit().call(arguments); 通过call()让arguments能够借用shfit()方法

绑定this时需要注意:

1. 给构造函数传入属性,注意构造函数的this属性

2.参数传进Con对obj的属性

3. 在Con内部手动指定函数执行时的this使用call、apply实现

最后我们需要返回一个对象
我们来测试一下:

function Person(name,age){
  this.name=name;
  this.age=age;
  this.say=function(){
    console.log('I am'+this.name)
  }

}

//通过new创建构造实例
let person1=new Person('Curry',18);
console.log(person1.name);// Curry
console.log(person1.age);// 18
person1.say(); // 'I am Curry'
//通过create方法创建实例
let person2=createNew(Person,'Curry',18)
console.log(person2.name)  // 'Curry'
console.log(person2.age). //'118'
person2.say();  // 'I am Cuury'

6、instanceof

instanceof 可以正确的判断对象的类型,因为内部机制是通过判断对象的原型链中是不是找到类型的prototype
我们可以试着实现一下 instanceof

function instanceof(left,right){
//获得原型的类型
let prototype=right.prototype;
//获得对象的原型
left=left.__proto__;
//判断对象的类型是否等于类型的原型
while(true){
  if(left===null)
      return false
  if(prototype===left)
    return true
    left =left.__proto__
}

}

7、this

function foo(){
console.log(this.a)
}
var a=1;
foo()

var obj={
a:2,
foo:foo
}
obj.foo()

//以上两种情况 this只依赖于调用函数前的对象,优先级是第二个情况大于第一个情况,以下情况是优先级最高的,this只会绑定在c上,不会被任何方式修改this指向
var c=new foo()
c.a=3
console.log(c.a) 
还有就是利用call,apply,bind改变this,这个优先级仅次于new

|看看箭头函数中的this

function a(){
    return ()=>{
      return ()=>{
        console.log(this)
    }
  }
}
console.log(a()()())

| 箭头函数其实是没有this的,这个函数中的this只取决于他外面的第一个不是箭头函数的函数的this。在这个例子中,应为调用a符合前面代码中的第一个情况,所以this是window。并且this一旦绑定了上下文,就不会被任何代码改变

相关文章

网友评论

      本文标题:2020-12-22

      本文链接:https://www.haomeiwen.com/subject/zyesnktx.html