数据类型:
JavaScript中也有对应的数据类型的划分:
- 四基两空一对象 , bigInt
- 四基: number(数值类型) 、string (字符串类型) 、 bool(布尔类型)、 symbol(符号类型)
- 两空: Null (空对象,空引用) Undefined (未定义的空值)
- 一对象: Object (对象类型,复杂数据,引用数据类型)
- 在JavaScript中除开基本数据类型以外,“万物皆对象”
例题
1~100中所有质数的和
// var num=2
// var sum=0
// var i=2
// var type
// while(num<=100)
// {
// while(i<=num){
// if(num%i==0){
// type=fasle
// break
// }
// i++
// }
// if(type){
// sum=sum+num
// }
// num++
// type=true
// i=2
// }
// console.log(sum);
函数作用域
作用域:var声明的变量以及function声明的函数在声明创建的时候,其作用域已经被确定了
全局作用域是无法访问到函数作用域中的变量或者函数
同级无法相互访问
无函数,不作用域
-全局作用
-函数作用域
作用域的作用划分变量和函数的使用区域
// 作用域链:
// 从里往外依次寻找,将多个作用域进行关联,形成隐式链条,通过这个链条可以访问上级作用域
函数调用时,隐式传入两个对象
// this
// arguments:用于接收函数调用时所传入的所有实参,arguments是一个类数组
this关键字:
当函数被调用时,运行环境会自动向该函数隐式传入this对象
this的指向是变化的,在不同情况下函数的执行中,this的指向是不一样的!
this 类似于语文上的 '这' 代表一个代词
1、当函数作为普通函数调用执行时 函数名()或IIFE 函数的this指向的是window
2、当函数作为某个对象的方法进行调用时,该方法中的this指向的是调用者,而非持有者!
// 对象名.方法() 表达式.方法() 对象名[方法名]()
闭包
正常情况下:局部作用域下声明变量或者函数,当该作用域中代码执行完毕后,该函数所声明的变量、函数就被销毁了
闭包:闭包就是当函数被嵌套声明时,并且该函数被直接和间接返回或者赋值给某个全局变量,
那么这个时候js内部发生一些事情
- 1、函数的地址值被返回了
- 2、产生了一个特殊的对象,闭包 (在这个闭包它打包了该函数作用域链上的所有的变量以及函数)
闭包面试题1
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()());
//面试题二
function fun(n, o) {//1、n=0 o=o alert()undefined n=1 n=2
alert(o)
return {
fun: function (m) {
return fun(m,n)//2、m=1 n=0 m=2 n=1 m=3 n=2
}
}
}
var a = fun(0); //un
var b=a.fun(1).fun(2)
a.fun(1); //0
a.fun(2); //0
a.fun(3); //0
var b = fun(0).fun(1).fun(2).fun(3);//un 0 1 2
var c = fun(0).fun(1) //un 0
c.fun(2)//1
c.fun(3)//1
原型属性
原型属性,每一个对象身上都具备一个属性,该属性称作为原型属性!
原型属性有两类:
- 显式原型属性 (prototype)
注意:每一个函数都具备 prototype,并且还具备__proto__
- 隐式原型属性 (__proto__)
注意:每一个实例对象,都具备 __proto__
原型对象
原型对象:存放在prototype属性或者__proto__属性中的对象,称作为原型对象
prototype,存放在该属性中的对象称作为显式原型对象
__proto__,存放在该属性中的对象称作为隐式原型对象
显式原型对象(prototype)的作用:
- 1、当函数作为构造函数使用,该属性才发发挥作用,如果是普通函数执行,原型对象毫无作用
- 2、当函数作为构造函数时,会创建一个实列的空对象
创建好空对象后,就会把 prototype中指向的原型对象赋值给 空对象的__proto__属性中
这样被创建好的空对象就具备了自己的原型对象!
注意:自定义的构造函数中prototy属性指向的默认是一个{}空对象
原生js提供的构造函数中的prototype是提前定义好的,基本不会是一个空对象
原型链
原型链:JavaScript通过每个实例对象上的__proto__隐式原型属性,将原型对象进行链接,在通过原型对象的原型属性
再进行链接,以此往复,直到最终的null,这样便形成了JavaScript中的原型链!
原型链的寻找一定是通过实例对象的 __proto__去寻找的!
牢牢的记住:
// 1、在js中所有的函数都是由Function构造函数创建的!包括Function自己
// 2、所有的原型对象都是Object的实例,Object.prototype除外
// 每一个原生的构造对象,所指向的prototype是不同的
function fun() {
this.a = 0
this.b = function () {
alert(this.a)
}
}
fun.prototype = {
name: 'yyy',
b: function () {
this.a = 20
alert(this.a)
},
c: function () {
this.a = 30
alert(this.a)
}
}
var my_fun = new fun()
alert(my_fun.a)
my_fun.b()
my_fun.c()
alert(my_fun.a)
my_fun.toString()
//0 0 30 30
2、
function Student(name, age) {
this.name = name
this.age = age
}
Student.prototype.fun = function () {
console.log('fun()')
}
var stu1 = new Student('小黑', 25)
console.log(stu1.name)
console.log(stu1.age)
stu1.fun()
this的劫持
正常情况下this的指向规则:
1、在全局作用域下访问this,this是指向window
2、当函数以函数形式调用时,this是指向window
3、当函数以 IIFE形式调用时,this是指向window
4、当函数以方法的形式调用时,this指向的是调用者,而非持有者
5、当作为构造函数调用时,this指向一个空对象 {}
除了以上正确情况下this的指向外,还有一些非正常情况!
this的劫持:强行的人为改变this的指向!
实现this劫持的三种方式(基于三个方法):apply call bind
- apply 和 call 用法基本一致
唯一不同之处:
apply 接受 两个参数 1、对象 2、数组 将其余参数统一存放到该数组中
call 接受任意个参数 1、对象 其余参数就是正常的函数执行所需要的实参逗号分隔
- bind
将函数进行改造后,并重新返回,最终执行!
箭头函数的this在被创建时就已经定死了无法被劫持
箭头函数
箭头函数,也是函数的一种!但是相比于其他的函数形式,它很特殊!
特殊:
1、写法特殊
2、不能作为构造函数使用
3、它不具备自己的this
4、箭头函数不具备自己的名字