继承就是一个对象可以访问另外一个对象中的属性和方法
const person = {
ears: 2,
eat: function () {
console.log('eating')//eating
},
hobby: ['reading', 'running'],
}
function Student(name, age) {
this.name = name
this.age = age
}
Student.prototype = person
Student.prototype.constructor = Student
Student.prototype.study = function () {
console.log('study hard!!!')
}
const s1 = new Student('zs', 16)
const s2 = new Student('zw', 24)
console.log(s1.ears)//2
s1.study()
s1.eat()
s2.hobby.push('coding')
console.log(s2.hobby)// ['reading', 'running', 'coding']
console.log(s1.hobby)// ['reading', 'running', 'coding']
console.log(person)//{ears: 2, hobby: Array(3), eat: ƒ, constructor: ƒ, study: ƒ}
原型继承->儿子的原型指向父实例对象,这样父实例对象的成员就可以实现继承
缺点: 继承的引用类型属性就一份,相互影响
继承方式: 构造函数继承 、原型继承 、组合继承、...
全局 this代表window
console.log(this) // window
函数直接调用 this代表window,函数内部开启严格模式, this指向undefined
function f() {
'use strict'
console.log(this) //undefind
}
事件的回调函数中 this->事件源
f() // window.f()
document.addEventListener('click', function () {
console.log(this)
})
构造函数的this->创建出来的对象
function Student() {
this.name = 'zs'
}
定时器->window
const s1 = new Student()
setInterval(function () {
console.log(this) // window
})
IIFE->window
;(function () {
console.log(this)
})()
谁调用函数,this就是谁
let obj = {
a: 10,
f: function () {
let a = 100
console.log(this.a)
},
}
obj.f()
let fn = obj.f
fn()
call函数作用 1 让函数执行 2 改变函数this指向
参数 第一个参数是this指,第二个参数开始传递给函数的实参
let obj = { name: 'longge', year: 12 }
function fn(x, y) {
console.log(this)//window//{name: 'longge', year: 12}
return x + y
}
fn(1, 3)
const res = fn.call(obj, 1, 3)
console.log(res)//4
console.log(Object.prototype.toString()) // [object Object]
console.log(Object.prototype.toString.call(123)) // [object Number]
console.log(Object.prototype.toString.call([])) // [object Array]
apply函数作用 1 让函数执行 2 改变函数this指向
参数 第一个参数是this指,第二个参数是一个数组,数组里放的是传递给函数的实参
let obj = { name: 'longge', year: 12 }
function fn(x, y) {
console.log(this)
return x + y
}
fn(1, 3)
const res = fn.apply(obj, [1, 3])
console.log(res)//4
console.log(Object.prototype.toString()) // [object Object]
console.log(Object.prototype.toString.apply(123)) // [object Number]
console.log(Object.prototype.toString.apply([])) // [object Array]
bind函数作用 改变函数this指向
参数 第一个参数是this指,第二个参数开始就是实际的参数
bind返回值一个新函数(改变this指向之后的函数),不会立即调用
let obj = { name: 'longge', year: 12 }
function fn(x, y) {
console.log(this)//window object
return x + y
}
fn(1, 3)
const res = fn.bind(obj, 1)
const r = res(5)
console.log(r)//6
arguments是函数内部的一个内置对象(伪数组) 接受所有实参
function f() {
console.log(arguments)
let sum = 0
Array.from(arguments).forEach(function (item) {
sum += item
})
for (let i = 0; i < arguments.length; i++) {
sum += arguments[i]
}
;[...arguments].forEach(function (item) {
sum += item
})
return sum
}
console.log(f())//0
console.log(f(1, 2))//9
console.log(f(1, 2, 3))//18
闭包 1 内部函数及其对外部变量的引用捆绑在一起
闭包 2 内部函数 + 外部函数(提供一个变量)
闭包 3 延伸变量的作用域、形成独立的作用域
4 原理: 作用域链
5 缺点:容易造成内存泄露(内存因某种原因无法释放)
function fn() {
let num = 10
function inner() {
console.log(num)//10
}
inner()
}
JS为我们声明的变量、函数等分配内存,当这些变量、函数、对象的内存不再使用->垃圾
垃圾回收(GC)机制
function f() {
let o = {
a: 1,
}
let o2 = {
b: 2,
}
o.b = o2
o2.a = o
}
f()
标记清除
标记 通过全局 标记所有从全局出发能够访问到的对象,不能够访问到的对象未被标记
function fn() {
c = {}
let o = {}
let o2 = {}
o.a = o2
o2.b = o
}
fn()
console.log(c)//object