一、this的指向
运行的时候才决定this的指向
function foo() {
console.log("foo函数",this)
}
// 1.直接调用
foo()// this => window
// 2.调用方式二,将函数放在一个对象当作
// 对象的一个属性
var obj = {
foo: foo,
}
obj.foo() // this => obj
this的绑定规则
1.默认绑定 =>就是独立函数调用
function foo() {
console.log("foo函数",this)
}
// 1.直接调用
foo()// this => window
// 2.函数定义在对象当中,但是是独立调用
var obj = {
name: "obj",
foo: function() {
console.log("foo函数", this);
},
}
var bar = obj.foo;
bar() // this => window
//3.高阶函数
function foo(fn) {
fn();
}
var obj = {
name: "cui",
bar: function () {
console.log("bar函数执行", this);//window
},
};
foo(obj.bar)
严格模式下,独立函数调用的this指向的是undefined
<script>
"use strict";
// 3.严格模式下 ,独立函数的调用this指向的时undefined
function fn() {
console.log(this);//undefined
}
fn();
</script>
2.隐式绑定
1.
function foo() {
console.log("foo函数", this); //obj
}
var obj = {
bar: foo,
};
obj.bar();
2.
function foo(){
console.log("foo函数",this)//obj1
}
var obj1 = {
foo:foo,
name:'obj1'
}
var obj2 = {
obj1:obj1
}
obj2.obj1.foo()
3.new绑定
/*
1.创建一个新的空对象
2.将this指向这个新对象
3.执行函数体中的代码
4.没有显示返回非空对象时,返回这个对象
*/
function foo() {
console.log("foo函数", this);//foo
this.name = "cui";
}
new foo();
4.显示绑定
4.1 apply(this,[传入的参数]) 第一个参数this,第二个参数传入一个数组 并调用函数
function foo(name,age,hegiht) {
console.log("this is", this, name,age,hegiht); // this is cui ["chen", 18, 180]
}
foo.apply("cui", ["chen", 18, 180]);
4.2 call(this,参数一,参数二)
function foo() {
console.log("this",this)
}
foo.call("cui","chen",18,180)
4.3 bind 创建一个新的函数改变this指向,不会自动执行函数
function foo(name, age, hegiht, adds) {
console.log("foo this is", this); //obj
console.log(name, age, hegiht, adds); //xiong 18 180 cd
}
const obj = { name: "cui" };
const bar = foo.bind(obj, "xiong", 18, 180);
bar("cd");
内置函数的调用绑定
1.定时器(this =>window) 按钮点击事件 (this => button)
2.forEach(函数,this) 箭头函数this指向window
const arr = ["cui", "chen", "zhi"];
arr.forEach(
function () {
console.log("this is", this);
}, "aaa");
比较优先级
1.显示绑定的优先级高于隐式绑定
2.new绑定优先级高于隐式绑定,new绑定不能与call和apply同时使用。new绑定的优先级高于bind
3.bind优先级高于apply/call
this绑定之外的情况
情况一:
1.非严格模式下 this绑定 null undefined 指向window
2.严格模式下 对应 null undefined
<script>
"use strict";
function bar() {
console.log(this)
}
bar.apply("aa")
bar.apply(null)
bar.apply(undefined)
</script>
情况二: (obj2.foo = obj1.foo)() 在这个时候表示独立函数调用,指向window
const obj1 = {
name: "obj1",
foo: function () {
console.log("foo", this);
},
};
const obj2 = {
name: "obj2",
};
(obj2.foo = obj1.foo)() //在这个时候表示独立函数调用,指向window
二、箭头函数
1.箭头函数不会绑定this、arguments属性
2.不能作为构造函数使用(不能和new一起来使用,会抛出错误)
完整写法
const foo =()=>{
console.log("箭头函数的函数体")
}
简写箭头函数
1.如果函数体当中只有一行代码,可以省略{}不能写return
const bar = ()=>console.log("箭头函数的函数体")
2.函数的参数只有一个时,可以省略()
const arr = ["cui","chee","chen","zhao"]
arr.map(item=>console.log(item))
3.如果函数返回是一个对象,必须加小括号()
const foo = () => ({ name: "崔" });
console.log(foo());//{ name: "崔" }
箭头函数的this
箭头函数压根没有this,查找规则会使this去找上层作用域
const bar = ()=>console.log("箭头函数的函数体",this)
bar()//window
this的查找规则
这里箭头函数没有this,但是会去上层作用与查找也就是foo这个函数,这个函数又被obj调用所以这里的this指向obj(注意对象的{}不是作用域)
const obj = {
name: "obj",
foo: function () {
const bar = () => {
console.log("bar", this); //obj
};
return bar;
},
};
const fn = obj.foo();
fn();
面试题
var name = "window";
var person = {
name: "person",
sayName: function () {
console.log(this.name);
}
};
function sayName() {
var sss = person.sayName;
sss(); // window
person.sayName(); // person
(person.sayName)(); // person
(b = person.sayName)(); // window
}
sayName();
var name = 'window'
var person1 = {
name: 'person1',
foo1: function () {
console.log(this.name)
},
foo2: () => console.log(this.name),
foo3: function () {
return function () {
console.log(this.name)
}
},
foo4: function () {
return () => {
console.log(this.name)
}
}
}
var person2 = { name: 'person2' }
// person1.foo1(); // person1
// person1.foo1.call(person2); // person2
// person1.foo2(); // window
// person1.foo2.call(person2); // window
// person1.foo3()(); // window
// person1.foo3.call(person2)(); // window
// person1.foo3().call(person2); // person2
// person1.foo4()(); // person1
// person1.foo4.call(person2)(); // person2
// person1.foo4().call(person2); // person1
var name = 'window'
function Person (name) {
this.name = name
this.foo1 = function () {
console.log(this.name)
},
this.foo2 = () => console.log(this.name),
this.foo3 = function () {
return function () {
console.log(this.name)
}
},
this.foo4 = function () {
return () => {
console.log(this.name)
}
}
}
var person1 = new Person('person1')
var person2 = new Person('person2')
// person1.foo1() // person1
// person1.foo1.call(person2) // person2
// person1.foo2() // person1
// person1.foo2.call(person2) // person1
// person1.foo3()() // window
// person1.foo3.call(person2)() // window
// person1.foo3().call(person2) // person2
// person1.foo4()() // person1
// person1.foo4.call(person2)() // person2
// person1.foo4().call(person2) // person1
var name = 'window'
function Person (name) {
this.name = name
this.obj = {
name: 'obj',
foo1: function () {
return function () {
console.log(this.name)
}
},
foo2: function () {
return () => {
console.log(this.name)
}
}
}
}
var person1 = new Person('person1')
var person2 = new Person('person2')
// person1.obj.foo1()() // window
// person1.obj.foo1.call(person2)() // window
// person1.obj.foo1().call(person2) // person2
// person1.obj.foo2()() // obj
// person1.obj.foo2.call(person2)() // person2
// person1.obj.foo2().call(person2) // obj
三、函数跟对象
函数的属性
//定义函数
function foo(a, b, c = 5, ...other) {}
function bar(m, n) {}
foo.message = "Hello, world!";
console.log(foo.message); //Hello, world!
//默认函数是有自己的属性的 ,函数默认有name属性就是函数的名字
//1.name属性
console.log(foo.name); //foo
//将2个函数放入一个数组当中
const arr = [foo, bar];
for (const fn of arr) {
console.log(fn.name);
}
//2.length属性,在函数当中接收参数的个数默认值不算
console.log(foo.length); //2 当前参数设置了默认值 c=5
console.log(bar.length); //2
//额外补充
// function test(...arr){
// console.log(arr)
// }
// test(1321321354,4654,6,46,54)
四、浏览器渲染原理
1.网页的解析过程
![](https://img-blog.csdnimg.cn/direct/09fed07f00ef491ba8dca95ef4136608.png)
2..浏览器的内核
![](https://img-blog.csdnimg.cn/direct/bd56bca050cf45aebc4db0fb949d24de.png)
3.回流和重绘
特殊解析 – composite合成
script元素和页面解析的关系
defer属性
![](https://img-blog.csdnimg.cn/direct/a12db46519304911b70188479ecd2656.png)
async属性
![](https://img-blog.csdnimg.cn/direct/2ca3ea702fd54d5ea04adcc4e1956c16.png)
五、声明变量的问题
var
1.允许重复的变量声明
var a = 1;
function print() {
console.log(a);
}
print(); // Output: 1
var a = 2;
print(); // Output: 2
2.变量的提升:怪异的数据访问 闭包问题