JavaScript进阶之OOP(二),web开发基础教程

所以一般情况,我们的公共属性定义到构造函数里面,公共的方法我们放到原型对象的身上


原型对象的this指向

谁调用,指向谁

1.在构造函数中,this指向的是对象实例

2.原型对象里面的this指向的也是调用它的实例对象

对象原型: __proto__

对象都会有一个属性 __proto__ 指向构造函数的prototype原型对象,之所以我们对象可以使用构造函数prototype原型对象的属性和方法,就是因为 __proto__ 的存在

实例化的对象.__proto__ === 构造函数名.prototype 返回true

constructor构造函数

对象原型(__proto__)和构造函数原型对象(prototype)里面都有一个constructor属性,constructor我们称为构造函数,因为它指回构造函数本身

主要目的:用于记录该对象引用于哪个构造函数(很多情况下我们需要用它来指回原来的构造函数)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-51Xs48DB-1615999328824)(jsOOP.assets/yuanxinglian-1609925587816.jpg)]

原型链

任何构造函数原型对象prototype,它作为一个对象,也有它自己的对象原型 __proto__ ,而此时原型对象的 __proto__ 指向的是Object.prototype, 即某构造函数名.prototype.__proto__ === Object.prototype

而我们Object也有prototype原型对象,而它作为一个对象,也有它自己的对象原型 __proto__ ,而此时指向null(到达了终点)

Object.prototype.__proto__ === null

JavaScript成员查找机制

所以在成员查找时,先查找最底层,没有则根据它 的__proto__查找至他的原型对象,看看有没有该成员,没有的话继续一层一层往上查找,如果找不到该成员 ,最后返回undefined (undefined是由null派生而来的)

而根据查找规则,使用就近原则来处理重复成员定义问题(即先找到,先使用)

在这里插入图片描述

拓展内置对象

可以通过原型对象,对原来的内置对象进行拓展自定义的方法,比如给数组增加自定义求偶数和的功能

//在Array原型对象上追加函数,不能采取Array.prototype = {}形式

Array.prototype.sum = function() {

let sum = 0;

for(let i = 0; i < this.length; i++){

sum+=this[i];

}

return sum;

}

4.继承


在ES6之前没有给我们提供extends,我们可以通过构造函数+原型对象模拟实现继承,被称为组合继承

call()

fun.call(thisArg, arg1, arg2....) (arg n那些指的是传递的其他参数)

功能:调用这个函数,并且修改函数运行时this的指向

thisArg: 当前调用函数的this的指向对象(一般在JavaScript中直接调用函数时,函数的this指向window)

ES5继承的两大步

借用构造函数继承父类型的属性

核心原理:通过call() 把父类型的this指向子类型的this,这样就实现了子类型继承父类型的属性

利用原型对象继承父类型的方法

实现如下:

// 借用父构造函数继承属性

function Father(uname, age) {

this.uname = uname;

this.age = age;

}

//接用父构造函数继承方法

Father.prototype.teach = function () {

console(‘father’)

}

function Son(uname, age) {

Father.call(this, uname, age);//改变父构造方法的this指向。

}

// 这样直接赋值会出问题,因为是赋值父原型对象的地址,如果修改了子原型对象,父原型对象也会随之改变

// Son.prototype = Father.prototype; ×

// 正确方法:

//让子原型对象指向父亲的一个实例,通过实例的__proto__指向父亲的原型对象就能拿到方法。

Son.prototype = new Father();

// 如果利用了对象形式修改了原型对象,别忘了利用constructor指回原来的构造函数

Son.prototype.constructor = Son;

Son.prototype.exam = function () {

console(‘son’)

}

let son = new Son(‘xxx’, 18);

console.log(son);

在这里插入图片描述

类的本质

class本质还是function(用typeof查看),所以我们可以认为类就是构造函数的另一种写法

但是新的class写法只是让对象原型的写法更加清晰,更像面向对象编程的语法

构造函数相同点:

1.类也有原型对象prototype,而prototype里的constructor也是指回类的本身

2.类也可以利用原型对象添加方法

3.类创建的实例对象中的 __proto__ 原型指向类的原型对象

5.ES5新增的方法


数组方法
1.forEach()

arr.forEach(function(vlaue, index, [array]))

分别对应数组的value(值)、index(索引号)、数组本身

遍历数组的全部元素,即使return true也不会终止迭代,因为forEach本质是一个函数,参数是一个回调函数,回调函数的return只是终止了回调函数而已,不是终止forEach,而forEach内部应该是多次调用了那个函数

var arr = [1, 2, 3];

var s = 0;

arr.forEach(function (value, index, arr) {

s += value;

})

console.log(s);

2.filter():

filter() 方法创建一个新数组,新数组中的元素是通过检查指定数组中符合条件的所有元素,主要用于筛选数组(注意它直接返回一个新数组

array.filter(function(currentValue, index, [arr]))

分别对应currentValue(数组当前项的值),index(索引号),arr(数组本身),它的回调函数返回的必须是一个Boolean值,返回true自动将value加入新数组中,false则过滤掉,最后整体返回一个新数组

var newArr = arr.filter(function(value, index) {

return value >= 20;

})

3.some()

some()方法用于检测数组中的元素是否 存在 满足指定条件,通俗点就是查找数组中是否有满足条件的元素,找到第一个满足条件的元素则停止

(注意它返回的是布尔值)在some里设置return true 以终止遍历

array.some(function(currentValue, index, [arr])) 分别对应currentValue(数组当前项的值),index(索引号),arr(数组本身)

var arr = [‘pink’, ‘red’, ‘green’];

var flag=arr.some(function (value, index, arr) {

return value == ‘pink’;

})

console.log(flag);

4.map()

方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。和forEach相似,不同在于:

如果更改数组内的值,forEach 不能确保数组的不变性。这个方法只有在你不接触里面的任何值时,才能保证不变性。由于它们之间的主要区别在于是否有返回值

map会制作一个新的数组,而forEach只会映射到原数组,所以可能改变原数组的值。

let newarr = arr.map(function(value, index) {

return value * 2;

})

map的不变性:当数组为基础类型时原数组不变

let array=[1,2,3,4,5]

let newArray=array.map((item) => item*2)

console.log(array); // [1,2,3,4,5]

console.log(newArray);//[2, 4, 6, 8, 10]

当数组为引用类型时原数组发生改变: map是浅拷贝

let array = [{ name: ‘Anna’, age: 16 }, { name: ‘James’, age: 18 }]

let newArray=array.map((item) => {

item.like=‘eat’;

return item;

})

console.log(array); // [{ name: ‘Anna’, age: 16,like: “eat”},{ name: ‘James’, age: 18,like: “eat”}]

console.log(newArray);//[{ name: ‘Anna’, age: 16,like: “eat”},{ name: ‘James’, age: 18,like: “eat”}]

5.every()

方法用于检测数组所有元素是否都符合指定条件

6.reduce

arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

参数分别对应回调函数(callback)和初始值(initialValue)对数组中所有内容进行汇总,有点像递归

let total = a.reduce(function (preValue, currValue) {

return preValue + currValue;

}, 0);

// 遍历到第一次时,preValue为初始值,currValue为数组里的第一个值

// 遍历到第二次时,preValue为第一次返回的值,currValue为数组里第二个数

以上ES5数组方法有助于链式编程(函数式编程),比如:

//this.$store.state.cartList 是一个数组

this.$store.state.cartList

.filter((item) => item.checked === true)

.reduce((preValue, item) => {

return preValue + item.count * item.price;

}, 0)

.toFixed(2);

forEach、some和filter区别

var arr = [‘pink’, ‘red’, ‘green’];

arr.forEach(element => {

if (element == ‘pink’) {

return true; //不会终止迭代

}

});

arr.some(e => {

if (e == ‘pink’) {

return true; //终止迭代,效率更高,适合查找唯一性元素。

}

});

arr.filter(e => {

if (e == ‘pink’) {

return true; //也不会停止迭代

}

});

字符串方法
trim()

方法会从一个字符串的两端删除空白字符,它并不影响本身的字符串,它返回的是一个新的字符串str.trim()

对象方法
Object.defineProperty()

定义对象中新属性或修改原有的属性(应用于vue响应式双向绑定,还有es5实现const的原理)

Object.defineProperty(obj, prop,desciptor)

obj:必须,目标对象

prop: 必需,需定义或修改的属性名

descriptor: 必须,目标属性所拥有的特性,一对象的形式{ }进行书写,

  • value设置属性的值,默认undefined;

  • writable值能否重写(修改),默认为false;

  • enumerable:目标属性是否可以被枚举(是否可以被遍历,显示出来),默认false;

  • configurable目标属性是否可以被删除,或者再次修改特性(是否可以再次更改这个descriptor),默认false;

  • 除此外还具有以下可选键值:

  • get:当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。

  • set:当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象(修改后的值)。

var obj = {

id: 1,

pname: ‘小米’,

price: 1999

}

//以前的对象添加修改方式

//obj.num = 1000;

//obj.price = 99;

Object.defineProperty(obj, ‘num’, {

value : 999,

enumerable : true

})

Object.keys(obj)

方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for…in 循环遍历该对象时返回的顺序一致 。如果对象的键-值都不可枚举,那么将返回由键组成的数组。

6.函数进阶


函数定义和调用

函数定义:

1.自定义函数:function fn() {};

2.匿名函数: var fun = function() {};

3.new Function('参数1', '参数2', '函数体')形式调用 像构造函数, Function里面的参数都必须是字符串格式(了解)

var f = new Function(‘a’, ‘b’, ‘console.log(a + b)’);

实际上所有的函数都是Function的实例,函数也属于对象

函数调用:
1.普通函数调用

function fn() {

//something

}

fn();

2.对象方法

var o = {

say: function() {

//something

}

}

o.say();

3.构造函数

function Star() {};

new Star();

4.绑定事件函数

btn.onclick = function() {}

5.定时器函数

setInterval(function() {}, 1000);

6.立即执行函数(自动调用)

(function() {} )();

7.this的指向


函数内this的指向

是当我们调用函数时确定的,调用方式不同导致this指向不同

1.普通函数调用:window

2.构造函数调用:实例对象,原型对象也是指向实例对象

3.对象方法:该方法所属对象

4.事件绑定:绑定事件对象

5 .定时器函数:window

6.立即执行函数:window

但是立即执行函数还得看这时this是否在对象方法或者构造函数中,第二个虽然是立即执行函数,但是它先找的是全局变量foo,再找到foo.bar,所以this返回的是foo作用域的a

var a = 1;

var foo = {

a: 2,

bar: function () {

return this.a;

}

};

console.log(foo.bar()); //2

console.log((foo.bar)()); //2

console.log((foo.bar=foo.bar)()); //1

“匿名函数的执行环境具有全局性”,所以最里层那个函数中this指向全局环境,全局环境没有定义foo变量所以输出undefined。在匿名函数外部将this保存到一个内部函数可以访问的变量self中,可以通过self访问这个对象,所以self.foo为bar

var myobject = {

foo: “bar”,

func: function () {

var self = this;

console.log(this.foo);

console.log(self.foo);

(function () {

console.log(this.foo);//undefined

console.log(self.foo);//bar

})();

}

};

myobject.func();

改变this指向

JavaScript为我们专门提供了一些函数方法来帮助我们处理函数内部this指向问题,常用的有bind()、call()、apply()三种方法

1.call()

前面讲过,call的主要作用可以实现继承

var obj = {

a:1

}

function f(){

console.log(this);

}

f.call(obj)

//call 第一个可以调用函数,还可以改变函数类this指向

//call 主要作用可以实现继承

2.apply()

方法调用一个函数,简单理解为调用函数的方式,但是它可以改变this的指向

fun.apply(thisArg, [argsArray])

thisArg:在函数执行时指定的this对象

argsArray: 传递的值,必须包含在数组(伪数组)里面

返回值为函数的返回值,因为它就是调用函数

应用方面:apply传递数组参数,所以可以借助数学内置对象求最大值 Math.max.apply(Math,arr)

var arr = [1,66,199,5,6]

//console.log(Math.max.apply(null,arr));

//严格模式,最好让thisArg指向Math

console.log(Math.max.apply(Math,arr));

//求数组最大值的其他方法

var ma = Math.max(…arr);

(es6拓展运算符…Math.max(...arr)也可以,但是不能 MAth.max(arr),因为max不接受数组,只接受一个一个的参数)

3.bind()

方法不会调用函数,但是能改变函数内部this指向

fun.bind(thisArg, arg1, arg2…)

返回指定this值和初始化参数改造的原函数拷贝

即创造新的函数 var f = fn.bind(xx)

应用方面:定时器等不想立即调用的函数(或者处理其他只能用that来暂时储存对象的情况)

//场景:点击按钮后,禁用按钮。3秒后恢复

btn.onclick = function() {

this.disabled = true;

//old way:

var that = this;

setTimeout(function() {

that.disabled = false;

}, 3000)

//new way:

setTimeout(function() {

this.disabled = false;

}.bind(this), 3000) //这个this指向btn

}

巧妙运用: 传参的时候可以传递其他对象过来

call、apply、bind总结

相同:改变函数内部的this指向。

区别

  1. call和apply会调用函数,bind不调用但返回一个改造过this的函数。

  2. call和bind传参为aru1,aru2…形式,apply必须数组形式[arg]

应用

  1. call经常做继承

  2. apply经常与数组有关系,比如借助数学对象求数组的最大值

  3. bind不调用函数,但想改变this指向,如定时器的内部this指向

8.严格模式


ie10以上版本才支持 它是让JavaScript以严格的条件下运行代码

  1. 消除了JavaScript一些语法不严谨的地方,减少怪异行为

  2. 消除代码一些不安全之处,保证代码运行的安全

  3. 提高编译器效率,增加运行速度

  4. 禁用了ECMAscript在未来版本中可能会定义的一些语法,为未来JavaScript做好铺垫,比如class、enum、super等

开启严格模式

应用到整个到整个脚本或个别函数中,因此,我们可以讲严格模式分为脚本开启严格模式为函数开启严格模式两种情况

为脚本开启严格模式:

方法二:(写在立即执行函数里的都要按照严格模式)

为函数开启严格模式:(只在此函数内部有严格模式)
变化
  1. 严格模式禁止变量为声明就赋值

  2. 严禁删除已声明的变量,比如delete x; 是错误的

  3. 在严格模式下,全局作用域中函数中的this不再是window,而是undefined(但是定时器之类的还是指向window)

  4. 严格模式下,如果构造函数不配合new来使用,this就会报错

  5. 函数不能有重名参数

  6. 函数必须声明在顶层,因为新版本的JavaScript引入了块级作用域,所以不允许在非函数代码块内声明函数

9.高阶函数


高阶函数是对其它函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出,最典型的就是作为回调函数

function fn(a, b, callback) {

console.log(a + b);

callback && callback();

}

fn(1, 2, function(){

console.log(‘我是callback’);

})

10.闭包


闭包指有权访问另外一个函数作用域中变量的函数,简单理解就是一个作用域可以访问另外一个函数内部的局部变量

被访问作用域的函数就是闭包函数

//在此处fun函数作用域访问了另外一个函数fn里面的局部变量num,形成了闭包,此时fn就是一个闭包函数

function fn() {

var num = 10;

function fun() {

console.log(num);

}

fun();

}

fn();

在fn外部作用域访问fn内部局部变量(它返回了当时的作用域):

//所以闭包就是典型的高阶函数

function fn() {

var num = 10;

return function() {

console.log(num)

}

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后

你要问前端开发难不难,我就得说计算机领域里常说的一句话,这句话就是『难的不会,会的不难』,对于不熟悉某领域技术的人来说,因为不了解所以产生神秘感,神秘感就会让人感觉很难,也就是『难的不会』;当学会这项技术之后,知道什么什么技术能做到什么做不到,只是做起来花多少时间的问题而已,没啥难的,所以就是『会的不难』。

我特地针对初学者整理一套前端学习资料,免费分享给大家,戳这里即可免费领取

前端路线图

闭包指有权访问另外一个函数作用域中变量的函数,简单理解就是一个作用域可以访问另外一个函数内部的局部变量

被访问作用域的函数就是闭包函数

//在此处fun函数作用域访问了另外一个函数fn里面的局部变量num,形成了闭包,此时fn就是一个闭包函数

function fn() {

var num = 10;

function fun() {

console.log(num);

}

fun();

}

fn();

在fn外部作用域访问fn内部局部变量(它返回了当时的作用域):

//所以闭包就是典型的高阶函数

function fn() {

var num = 10;

return function() {

console.log(num)

}

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-6LUvb1JL-1712124156568)]

[外链图片转存中…(img-WttHxBl9-1712124156569)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

[外链图片转存中…(img-emqJm2nC-1712124156569)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后

你要问前端开发难不难,我就得说计算机领域里常说的一句话,这句话就是『难的不会,会的不难』,对于不熟悉某领域技术的人来说,因为不了解所以产生神秘感,神秘感就会让人感觉很难,也就是『难的不会』;当学会这项技术之后,知道什么什么技术能做到什么做不到,只是做起来花多少时间的问题而已,没啥难的,所以就是『会的不难』。

我特地针对初学者整理一套前端学习资料,免费分享给大家,戳这里即可免费领取

[外链图片转存中…(img-Px5mNdDr-1712124156570)]

vue.js的36个技巧

  • 11
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 现代javascript教程是一本深入浅出、全面介绍现代JavaScript开发的教程。它提供了一个PDF版本,方便读者在离线状态下学习和参考。 这本教程首先介绍了JavaScript语言的基础知识,包括变量、数据类型、运算符、流程控制等等。然后,它深入讲解了JavaScript中的函数,包括函数的定义、调用、参数、返回值等等。接着,教程详细介绍了JavaScript中的对象和数组的使用,以及如何使用它们来处理和组织数据。 在基础知识讲解之后,教程进一步介绍了JavaScript中的面向对象编程(OOP),包括类、继承、封装等。然后,它详细讲解了异步编程的概念和常用的异步编程模式,如回调函数、Promise和async/await等。此外,教程还介绍了模块化开发的概念和实践,以及如何使用现代的工具和框架来提升开发效率和代码质量。 这本教程的特点是以实际案例为基础进行讲解,给读者提供了大量的练习题和示例代码。它注重培养读者的实际编程能力,让读者能够独立地进行JavaScript开发。 总的来说,现代JavaScript教程PDF是一本很好的学习资源,无论是初学者还是有经验的开发者都可以从中受益。它涵盖了JavaScript开发的方方面面,并且提供了丰富的实例和练习,帮助读者更好地理解和应用所学知识。 ### 回答2: 现代JavaScript教程PDF是一本非常受欢迎的学习资源,可以帮助初学者快速入门并深入了解JavaScript编程语言。该教程由大量的实例和范例代码组成,以简洁明了的方式向读者介绍了JavaScript的基础知识和高级概念。 这本教程首先从JavaScript的历史和发展讲起,然后逐步引导读者了解JavaScript的语法、数据类型、运算符和控制流程等基础知识。接下来,它深入探讨了JavaScript的对象、函数、闭包和原型链等高级主题,帮助读者建立起扎实的JavaScript编程基础。 该教程还介绍了许多常用的JavaScript库和框架,如React、Vue和Angular,这些工具可以帮助开发者快速构建现代化的Web应用程序。此外,教程还涵盖了JavaScript中的异步编程、模块化开发和错误处理等重要内容,帮助读者提高编程效率和代码质量。 PDF格式的教程使得学习更加便捷,读者可以在电脑、平板或手机上阅读和学习,随时随地获取知识。同时,PDF格式也使得读者可以方便地进行搜索、书签和注释等操作,加深对内容的理解和记忆。 总之,现代JavaScript教程PDF是一本全面而深入的学习资源,适用于初学者和有一定基础的开发者。它通过清晰的解释和实例代码,帮助读者掌握JavaScript的核心概念和技术,成为一名熟练的JavaScript开发者。 ### 回答3: 现代JavaScript教程是一本广泛流行的JavaScript编程指南,它的PDF版本可以免费在互联网上找到。这本教程由Muhammad Yasoob Ullah Khalid编写,涵盖了JavaScript语言的许多方面,并提供了丰富的示例和解释。 PDF版本的现代JavaScript教程可以让读者在没有网络连接的情况下随时随地学习JavaScript编程知识。与在线版本相比,它具有更高的灵活性和便携性。 这本教程的内容非常全面,从基础知识开始介绍,如变量、数据类型、运算符等,然后逐步深入介绍JavaScript的核心概念,如条件语句、循环、函数等。此外,它还涵盖了JavaScript的高级主题,如DOM操作、事件处理、异步编程等。这些内容旨在帮助读者全面掌握JavaScript编程技术。 现代JavaScript教程的特点之一是它提供了大量的实践示例,读者可以通过这些示例来加深对JavaScript概念和技术的理解。此外,教程还附带了一些挑战和题目,读者可以通过解决这些问题来提高他们的编程能力。 总之,现代JavaScript教程是一本全面且易于理解的JavaScript编程指南,可以帮助读者系统性地学习和掌握JavaScript编程技术。无论是初学者还是有经验的开发人员,都可以通过阅读PDF版本的现代JavaScript教程来提升他们的JavaScript编程技能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值