JS高级的学习(二)
JS高级的学习(二)
set对象
- Set 是一个对象 存放数据 数据永远不会重复
- Set 当成是一个数组 遍历 使用 数组方法 find findIndex Map
- 数组转成 Set对象 const set = new Set([])
- Set对象转成 数组 const arr=[…set]
// 旧的数组const list = [1, 2, 3, 4, 5]// 1.Set对象 需要被 new 出来使用// const set = new Set()const set = new Set(list)// 2.存放数据 调用 add方法set.add(7)set.add(8)set.add(8)set.add(9)console.log(set)// 3.把set对象 转成数组const arr = [...set]console.log(arr)
创建对象的n种方式
- 字面量 不方便维护,修改
- 工厂函数 封装 继承,参数一多也很麻烦
- 重点介绍 构造函数
// 创建对象的方式:// 字面量 不方便维护 - 修改// const obj = { nickname: '悟空', height: 190 }// const obj1 = { nickname: '八戒', height: 100 }// const obj2 = { nickname: '沙和尚', height: 80 }// 工厂函数 封装 继承,参数一多也很麻烦function person(name, height, a, b, c, d, e) {return {nickname: name,height,a,b,c,d,e,}}const obj = person('悟空', 190)const obj1 = person('八戒', 100)const obj2 = person('沙和尚', 80)console.log(obj)console.log(obj1)console.log(obj2)// 最重要的是 构造函数
箭头函数 没有this指向
- 箭头函数没有内部的this
- 当函数执行体代码中 有出现了 this 慎用 箭头函数
const obj = {username: "悟空",say: () => console.log(this) // this指向window}const funct1 = () => console.log(this) // this指向windowobj.say()funct1()const button = document.querySelector("button")button.addEventListener("click", function () {this.innerText = "被修改了哈哈"console.log(this) // 按钮本身})button.addEventListener("click", () => {// this.innerText = "被修改哈" // error,this指向window了console.log(this) // window})
全局函数的this的指向
- 一般来说 this的指向 判断依据 谁调用了 函数 this 指向谁
- 其实 当定义了全局的函数的时候,默认是挂载到了window 全局变量上
- 全局函数 其实就是 window的一个属性而已 只不过 平时写代码的时候 可以省略这个window
- 当定义全局的函数的时候 本质是给window添加了一个 属性(函数类型)
- 当调用这个函数的时候 如:person() 本质 window.person() window 可以被省略而已
function person() {console.log("ABC")console.log(this) // this指向window}person() // 调用了this,this指向了windowwindow.sonPerson = function () {console.log('ABC')console.log(this) // this指向window}window.sonPerson() // 调用了this,this指向了windowconst obj = {username: "悟空",say() {console.log(this) // this指向obj}}obj.say()
构造函数
构造函数 本质 其实也是一个函数
作用 用来创建对象
以前见过构造函数
只要它被new 它就是构造函数
- 如:Person 构造函数 首字母是大写(规范)
- 如:per 被new出来的对象是 实例
// Person 就是一个构造函数 被newfunction Person() {}// per 就是实例const per = new Person()
构造函数的this
- 每一个构造函数中 都存在 一个 魔鬼 this
- 构造函数 默认情况下 就是返回了 this
- this 等于你所new出来的实例
// 只要给构造函数中的this 添加 属性或者方法// 那么 实例 自然拥有对应的属性和方法function Person() {this.username = '悟空' // Person增加了一个属性this.add = function () {} // Person增加了一个方法this.clear = function () {}}// 注意:console.log(Person.username) // 无法拿到Person的元素console.log(Person.username = '沙和尚') // 控制台显示 沙和尚,但实际Person里面的username还是 悟空console.log(Person) // username属性还是 悟空console.log(this.username) // 无法拿到Person的元素const per = new Person()per.nickname = '八戒' // 直接添加,per有、per2没有const per2 = new Person()console.log(per)console.log(per2)console.log(per2.username) // 可以拿到Person的元素
构造函数的弊端
function Person() {this.say = function () {}}// p1 和 p2 没有共享一个方法(占更多的内存)const p1 = new Person()const p2 = new Person()console.log(p1 === p2) // false 两个对象的比较 内存地址 console.log(p1.say === p2.say) // false 两个函数 存放在不同地址中// s1 和 s2 共享一个方法const s1 = new Set()const s2 = new Set()console.log(s1 === s2) // false 两个对象的比较 内存地址 console.log(s1.say === s2.say) // true 两个函数 存放在相同地址中
构造函数-方法指向同一个(这个全局(方法)变量不推荐,后面的 构造函数+原型 更好 )
- 值类型 是存在 栈空间 适合存放 固定大小的数据
- 引用类型(对象、数组、函数) 存在 堆空间 适合存放大小不固定的数据
- new了两个对象的时候, 两个对象的内存地址 不相等
- 希望 两个对象的方法 内存地址是相等
- 在构造函数中 当我们定义方法的时候 一般都不会只在 构造函数中写死
- 让 方法 都指向外部 单独声明的方法 多个实例去共享方法
- 缺点:污染全局变量,意思是有其他人可能使用这些属性、方法,就会造成覆盖
// newSay 全局(方法)变量function newSay() {console.log('外部单独的newSay方法')}function Person() {this.say = newSay}const p1 = new Person()const p2 = new Person()console.log(p1 === p2) // false console.log(p1.say === p2.say) // true
构造函数基本使用(这个全局(方法)变量不推荐,后面的 构造函数+原型 更好 )
- 构造函数的属性
- 函数类型的属性(指方法):一般都是写在外部
- 非函数类型的属性(指属性):一般是写在内部
// say 全局(方法)变量function say() {console.log('这个是Person的一个方法', this.name)}// fly 全局(方法)变量function fly() {console.log(this.name, '要起飞')}function Person(name, height) {this.name = namethis.height = heightthis.say = saythis.fly = fly}const p1 = new Person('八戒', 150)p1.say()p1.fly()console.log(p1)console.log(p1.name, p1.height)
构造函数+原型(es6比es5(构造函数+原型)更好)
- 原型 本质 是一个对象
- 当创建一个构造函数的时候 原型 就被创建了
- 如果我们在原型对象上 增加一个属性或者方法 那么 实例 拥有所增加的属性或者方法
- 原型 就是 DNA;构造函数 就是 父亲;实例 就是 孩子
function Person() {this.name = '悟空'this.b = function () {}}console.log(Person.prototype)// 访问原型Person.prototype.a = function () {console.log('这个是a方法')}const p1 = new Person()console.log(p1)p1.a()
原型实现方法的继承-prototype
function Person() {}Person.prototype.say = function () {console.log('father', '父亲定义的say方法')}const father = new Person()function SonPerson() {}// 让孩子SonPerson去复用父亲Person的方法 即继承父亲的方法SonPerson.prototype.say = Person.prototype.say// 添加其他方法SonPerson.prototype.jump = function () {console.log('son', '孩子自己的方法')}const son = new SonPerson()Person.prototype.say() // ok:Person的原型(prototype)的方法say()SonPerson.prototype.say() // ok:SonPerson的原型(prototype)的方法say()// son.say = father.say // 等同于 SonPerson.prototype.say = Person.prototype.say 前提条件:Person和SonPerson都被 new 后son.say()son.jump()
原型实现属性的继承-call
function Person(name, color, height, weight) {this.name = namethis.color = colorthis.height = heightthis.weight = weight}function SonPerson(name, color, height, weight, nickname, gender) {// Person父亲中也有 注意:this不能忘写Person.call(this, name, color, height, weight) // 属性的继承 // SonPerson孩子this.nickname = nicknamethis.gender = gender}const son = new SonPerson('悟空', '黄色', 150, 250, '弼马温', '公')console.log(son)console.log(son.name)
原型快速继承
// 作用:快速将父亲的原型复制到儿子上function Person() {}Person.prototype.add = function () {}Person.prototype.remove = function () {}Person.prototype.clear = function () {}function SonPerson() {}// SonPerson.prototype.add= Person.prototype.add// SonPerson.prototype.remove= Person.prototype.remove// SonPerson.prototype.clear= Person.prototype.clear// 让儿子的原型 指向 父亲的原型// SonPerson.prototype = Person.prototype // error:堆地址联系在一起,修改一个,另一个也被修改// 对象复制(剩余运算符)SonPerson.prototype = {...Person.prototype}SonPerson.prototype.cunstructor = SonPerson // 添加方法到SonPerson的原型SonPerson.prototype.del = function () {} // 添加方法到SonPerson的原型const son = new SonPerson()console.log(son)const per = new Person()console.log(per)
es6类的基本使用
- 构造函数 来创建对象
- 对象 两种属性信息
- 非函数类型的属性(指属性)
- 函数类型的属性(指方法)
// es6 新 简洁 class 面向对象class Person {// this不用写,一写就报错name = '悟空'color = '红色'say() {console.log(this.name, this.color)}fly() {console.log(this.name, '起飞')}}// es5 原型链方式实现 面向对象function Person2() {this.name = "悟空"this.color = "紫色"}Person2.prototype.say = function () {console.log(this.name, this.color)}Person2.prototype.fly = function () {console.log(this.name, '降落')}const p1 = new Person()p1.say() // 悟空 红色p1.fly() // 悟空 起飞const p2 = new Person2()p2.say() // 悟空 紫色p2.fly() // 悟空 降落
es6类的(动态)基本使用
// 使用 class 来定义属性的时候// 1.如果 这个属性 写死了// class Person {// name="悟空"// color="黄色"// }// 2.如果 属性 可以由外部传入 必须使用构造器// constructor(name,color){// this.name=name// this.color=color// }class Person {// 构造器constructor(name, color) {// 当 Person被new的时候 这个构造器 就会被调用console.log('Person被new了')console.log(name, color)// this 还是指向 实例 注意:this要写this.name = namethis.color = color}say() {console.log(this.name, this.color)}}const p1 = new Person('悟空', '红色')p1.say()console.log(p1)
es6类实现属性和方法的继承
// // es5类 去实现继承// function Person() {// this.name = "父亲"// }// Person.prototype.say = function () {// console.log(this.name, "父亲的say方法")// }// function SonPerson(name) {// Person.call(this, name) // 属性的继承// }// SonPerson.prototype.say = Person.prototype.say // 方法的继承// const son = new SonPerson// console.log(son.name)// son.say()// es6类 去实现继承class Person {name = '父亲'say() {console.log(this.name, '父亲的say方法')}}// 直接实现了 继承父亲的属性和方法class SonPerson extends Person {}// 孩子实例 拥有 父亲 name属性和say方法const son = new SonPerson()console.log(son)console.log(son.name)son.say()
es6类实现(动态)属性和方法的继承
// 对于孩子来说 // 1.如果写了 extends 而且 还写 constructor // 那么在 constructor 必须要调用super 固定语法// 2.之前只写 extends 不用写super 因为没有写 constructorclass Person {constructor(name, color) {this.name = namethis.color = color}say() {console.log(this.name, this.color)}}class SonPerson extends Person {// 默认的代码constructor(name, color, height, weight) {super(name, color) // 调用父亲的构造器 给孩子 添加属性this.height = heightthis.weight = weight}}const son = new SonPerson('悟空', '紫色', 100, 200)console.log(son)console.log(son.height)son.say()
检测数据类型(检测实例被这个构造函数 new)
// 检测 基本的数据类型 typeof// 检测 引用数据类类型 intanceof// 检测 这个实例是不是被某个构造函数 new 出来 console.log(typeof '') // stringconsole.log(typeof 1) // numberfunction Person() {}class SuperPerson {}const p1 = new Person()const s1 = new SuperPerson()console.log(p1 instanceof Person) // trueconsole.log(s1 instanceof SuperPerson) // trueconsole.log(p1 instanceof SuperPerson) // false
对象中的this和call
- this 范围很广 主要在 对象中来学习
- this 指向 对象本身 可以通过 call 方法来修改
- call 在调用方法的时候,可以修改 this 的指向
- call 在调用方法的时候,可以传递参数
const obj = {height: 100,username: '悟空',say(a) {console.log(this, a) // this指向 obj},}const newObj = {username: '八戒'}obj.say()console.log(obj)obj.say.call() // call修改this的指向,变成windowconsole.log('----------------------------------')obj.say(123)obj.say.call(this, 123) // this指向 windowobj.say.call(newObj, 123) // this指向 newObj
对象添加属性的方式
// 对象添加属性的普通方式const newObj = {a: 1,b: 1,}newObj.c = 2console.log(newObj)// 在对象中 this = 对象本身 this = 我自己// 当成普通的对象const obj = {a: 1,e: 1,add() {// 给对象添加属性 封装到一个普通的函数中obj.a = 3 // 会覆盖原来的a属性obj.b = 3// 等同上面 obj修改成thisthis.c = 4this.d = 4}}console.log(obj) // add方法没使用时,只有a、e、add()obj.add() // 让方法帮我们添加属性console.log(obj)
动态给对象添加属性-call
// 当成普通的函数function person(name, color, height, weight) {this.name = namethis.color = colorthis.height = heightthis.weight = weight}// 定义一个空的对象const obj = {}person.call(obj, '悟空', '红色', 150, 250) // obj 借用了person方法 来给自己的属性赋值// 1.调用了 Person 方法// 2.方法内部 给 this赋值 this 等于 obj// 3 this.name=悟空 => obj.name = 悟空 // 赋值动作 // 3 this.color=黄色 => obj.color = 黄色 // 赋值动作 // 3 this.height=150 => obj.height = 150 // 赋值动作 // 3 this.weight=250 => obj.weight = 250 // 赋值动作console.log(obj) // 拥有了 Person 函数中一些属性
修改this指向:bind、call、apply
- call 和 apply 会在调用原函数的同时也修改this的指向
- bind会修改this指向 但是 不会直接调用原函数 而是会返回一个 修改了this指向 的新函数
- call 和 apply 区别 传递参数的方式不同而已
- 如:obj.say.call(newObj,1,2) // 数字,字符串
- 如:obj.say.apply(newObj,[1,2]) // 数组
- 默认情况下 this的指向 谁调用了this,this 指向谁
const obj = {username: '悟空',say() {console.log(this.username, 'obj中的say方法 ')},say1(a, b) {console.log(a, b)},}const newObj = {username: '八戒',}obj.say.call(newObj)obj.say.apply(newObj)const fn = obj.say.bind(newObj) // 返回一个新的函数 新函数内部 修改this指向的功能fn()console.log('---------------------------')obj.say1.call(newObj, 1, 2)obj.say1.apply(newObj, [1, 2]) // 参数必须要以数组的形式来传递const fn1 = obj.say.bind(newObj)fn1(1, 2)
JS高级的学习(二)相关推荐
- JS高级——模块化学习笔记
一.什么是模块化? 到底什么是模块化.模块化开发呢? 事实上模块化开发最终的目的是将程序划分成一个个小的结构: 这个结构中编写属于自己的逻辑代码,有自己的作用域,不会影响到其他的结构: 这个结构可以将 ...
- JavaScript高级程序设计学习(二)之基本概念
任何语言的核心都必然会描述这门语言基本的工作原理.而描述的内容通常都要涉及这门语 言的语法.操作符.数据类型.内置功能等用于构建复杂解决方案的基本概念.如前所述, ECMA-262通过叫做 ECMAS ...
- js高级程序设计学习
1 script标签 1.1 script标签属性 src:指定加载的外部js文件 type:在浏览器中为"text/javascript",如果加载或包含ES模块代码,值为mod ...
- c++面向对象高级编程 学习二 带指针的类
带指针的类,必须要自己写拷贝构造和赋值构造 拷贝构造:参数和类的类型一样的构造函数 赋值构造:重写操作符=,且其参数和类的类型一样 class String {public: String(const ...
- Node.js高级编程【一】node 基础
目录 一.Node 基础 1.课程概述 2.Node.js 架构 3.为什么是Node.js ? 4.Node.js 的 异步IO 5.Node.js 主线程是单线程 6.Node.js 应用场景 7 ...
- Js高级程序设计第三版学习(十二章)
Js高级程序设计第三版学习(十二章) 第十二章 DOM2和DOM3 1.样式: 访问样式属性 任何支持style特性的HTML元素都有一 ...
- day04【JS高级】BOM对象、Window对象、二种定时器、 Location对象、DOM对象、DOM获取元素、DOM操作内容、DOM操作属性、DOM操作样式、DOM操作元素(标签)、 正则表达式
回顾 1. js基础语法运算符:算数运算符可以与字符串进行数学运算,js底层进行隐式转换比较运算符:===(恒等) 特点,比较类型+内容流程控制语句if判断条件表达式:1)布尔2)数值:非0为真3)字 ...
- Js 高级学习教程
一.Js 高级学习教程 1.Js BOM.DOM 基础概念 2.Js BOM 6大对象 3.Js 定时器使用 4.Js 本地存储 5.Js Dom 操作基本逻辑 6.Js Dom 事件注册 7.Js ...
- Python学习 Day26 JS循环语句(二)
JS循环语句(二) (一)寻找质数 输出1-100之间的质数 for(var num = 1;num <= 100;num++){//累加器,只要遇到是数字num的约数,这个变量就进行+1var ...
最新文章
- 2019年终总结--满城灯火,只若初见
- Flume监听文件夹中的文件变化,并把文件下沉到hdfs
- python open文件安全隐患_python的其他安全隐患
- STL模板整理 set
- 这些Intel Atom处理器千万别升Windows 10创意者更新:不兼容
- 西北师范大学知行学院计算机科学与技术,西北师范大学知行学院电子信息工程专业...
- HBase数据模型解析和基本的表设计分析
- File类之常用方法
- React后台管理系统-订单管理
- Jasper报表导出pdf中文不显示——Font simsun is not available to the JVM. See the Javadoc for more det,已解决
- c语言智能车跑道检测程序,智能小车的循迹方法与流程
- SQL Server中查询累计和与滑动平均值
- 用友NC系统与一卡通集成解决方案
- Windows中使用Termius
- android 读build.prop,Android build.prop简介
- 外卖店优先级 第十届蓝桥杯真题 C++
- 使用 Ceph 作为 OpenStack 的统一存储解决方案
- 氧分呗:新时代定义科技的美好 自主创新踏上新征程
- 一杯清茶的时间G-TEA泉舟精英
- 2019,先定个小目标