Js进阶

面向过程POP

Javascript进阶

面向过程POP

  (process-oriented programming)分析出解决问题所需的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用就可以了

面向对象OOP

(object oriented programming)把事务分解成一个个对象,然后由对象之间分工合作。

OOP的特性:封装性,继承性,多态性

对象是一组无序的相关属性和方法的集合。

【类class】

创建类  class name {

          }

创建实例  var xx = name(); 类必须使用new实例化对象

类constructor构造函数

constructor()方法是类的构造函数(默认的方法),用于传递参数,返回实例对象,通过new命令生成对象实例时,自动调用该方法,如果没有显示定义,类内部会自动给我们创建一个constructor()

语法:

class Person {

    constructor (name,age) {  //构造方法或构造函数

          this.name = name;

          this.age = age;

    }

    say () {

    }

}

var ldh = new Person('刘德华',18);

继承extends

class Father {

}

class Son extends Father {

}

【super】关键字-访问和调用对象父类上的函数

class Person {

    constructor (surname) {

      this.surname = surname;

  }

}

class Student extends Person { //子类继承父类

    constructor (surname,firstname) {

      super(surname);  // 调用父类的constructor(surname)

        this.firstname = firstname;//定义子类独有的属性

    }

}

注意:super必须放到this前面✔

super用于访问和调用对象父类上的函数,可以调用父类的构造函数,也可以调用父类的普通函数

在ES6中类没有变量提升,所以必须先定义类,才能通过类实例化对象。

类里面的共有属性和方法一定要加this使用。

类里面的this指向问题。

constructor 里面的this指向实例对象,方法里面的this指向这个方法的调用者。

insertAdjacentHTML(追加的位置,'要追加的字符串元素')-可以直接把字符串格式的元素添加到父元素中。不可以用appendChild追加。

追加的位置-beforeend插入元素内部的最后一个子节点之后。

禁止选中文字

window.getSelection?window.getSelection().removeAllRanges() : document.selection.empty();

构造函数-一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与new一起使用,我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。

在Js中使用构造函数时需要注意以下两点∶

构造函数用于创建某一类对象,其首字母要大写。构造函数要和new一起使用才有意义。

new在执行时会做四件事:

在内存中创建一个新的空对象。

让this指向这个新的对象。

执行构造函数里面的代码,给这个新对象添加属性方法。

返回这个新对象(所以构造函数里面不需要return)

构造函数可以添加一些成员,可以在构造函数本身上添加,也可以在构造函数内部的this上添加。通过这两种方法添加的成员分别称为静态成员和实例成员。

静态成员:在构造函数本身上添加的成员,只能由构造函数本身来访问。

实例成员:在构造函数内部创建的对象成员,只能由实例化的对象来访问。

构造函数原型prototype

构造函数通过原型分配的函数是所有对象所共享的,js规定,每一个构造函数都有一个prototype 属性,指向另一个对象。注意这个prototype就是一个对象,这个对象的所有方法和属性,都会被构造函数所拥有。我们可以把那些不变的方法直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法。

原型是什么-一个对象,我们也称为prototype为原型对象。作用是共享方法。

function Star (uname,age) {

    this.uname = unane;

    this.age = age;

}

Star.prototype.sing = function (){

}//在原型上添加共有方法

对象原型__proto__

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

__proto__对象原型和原型对象prototype是等价的,

__proto__对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条线,但是它是一个非标准属性,因此实例开发中,不可以使用这个属性,它只是内部指向原型对象prototype.

三者之间关系

Star构造函数通过Star.prototype指向Star原型对象prototype

Star原型对象prototype通过原型对象.constructor指向Star构造函数

Star构造函数直接指向它的ldh实例化对象

ldh对象实例通过ldh.__proto__指向Star原型对象prototype

__proto__和prototype里面都有一个constructor 属性,constructor我们称为构造函数,因为它指向构造函数本身。

constructor主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。

JS查找机制

先查找自身属性-再查找原型-查找对象的原型Object 的原型-null

__proto__的意义就在于为对象成员查找提供一个方向,或者说一条路线。

原型对象this指向

构造函数里的this指向实例对象。

原型对象里面放的是方法,这个方法里面的this指向的是这个方法的调用者,也就是这个实例对象。

通过原型对象,对原来的内置对象进行扩展自定义的方法。

继承【继承】

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

call()方法

fun.call(thisArg,arg1,arg2...)

thisArg:当前调用函数this的指向对象

arg1:传递的其他参数

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

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

function Father (name,age) {

    this.name=name;

    this.age=age;

}

function Son (name,age,sex) {

    Father.call(this,name,age);//父类的this指向子类的this,.同时调用这个函数

    this.sex=sex;

}

var xt= new Son('ez','18','男');

借用原型对象继承父类型方法

一般情况下,对象的方法都在构造函数的原型对象中设置,通过构造函数无法继承父类方法。核心原理-

将子类所共享的方法提取出来,让子类的prototype原型对象=new 父类(),

本质-子类原型对象等于是实例化父类,因为父类实例化之后另外开辟空间,就不会影响原来父类原型对象,将子类的constructor 重新指向子类的构造函数。

类的本质

class的本质还是function

类的所有方法都定义在类的prototype属性上

类创建的实例,里面也有__proto__指向类的prototype原型对象

ES6的类它的绝大部分功能,Es5都可以做到,新的class写法只是让对象原型的写法更加清晰,更像面向对象编程的语法而已

ES5新增的方法

数组方法

foreach()

array.foreach(function(currentValue,index,arr){})

currentValue:数组当前项的值

index:数组当前项的索引号

arr:数组对象本身

arr.foreach(function(value,index,array){

//函数内部可以获取到参数值

    })

filter()筛选元素,返回新数组

array.filter(function(value,index,array){

//函数内部可以获取到参数值

    })

currentValue:数组当前项的值

index:数组当前项的索引号

arr:数组对象本身

返回一个新数组,新数组中的元素是通过检查指定数组中符合条件的所有元素,主要用于筛选数组。

例子-

var arr=[12,66,4,88,3,7];

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

  return value%2===0;

});

some()查找元素,返回布尔值

array.some(function(value,index,array){

//函数内部可以获取到参数值

    })

currentValue:数组当前项的值

index:数组当前项的索引号

arr:数组对象本身

用于检测数组中的元素是否满足指定条件,查找数组中是否满足条件的元素。

返回布尔值,如果查到这个元素就返回true,查不到返回false.

找到你一个满足条件的元素,则终止循环,不再继续查找。

把数据渲染到页面-foreach

根据价格显示数据-filter

字符串方法

str.trim(),删除字符串两端的空白字符,不影响原字符串本身,返回新字符串,可用于用户输入空格失去焦点时清空表单。

对象方法

Object.keys(obj)用于获取对象自身所有属性

类似for...in

返回一个由属性名组成的数组。

Object.defineProperty(obj,prop,descriptor)

obj-必需,目标对象

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

descriptor-必需,目标属性所拥有的特性,以对象{}形式书写,value:设置属性的值,默认undefined

writable:值是否可以重写,true|false,默认为false

enumerable:目标属性是否可以被枚举,true|false,默认为false

configurable:目标属性是否可以被删除或是否可以再次修改特性true|false,默认为false

定义对象中新属性或者修改原有属性。

改变函数内部this指向

1.call方法

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

fun.call(thisArg,arg1,arg2...)

thisArg:在fun函数运行时指定的this值

arg:传递的其他参数

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

因此当我们想改变this指向,同时想调用这个函数,可以使用call,比如继承

2.apply方法

fun.apply(thisArg,[argArray])

thisArg:在fun函数运行时指定的this值

argArray:传递的值,必须包含在数组里面

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

因此apply主要和数组有关,比如使用Math.max()求数组的最大值

var arr=[1,66,3,99,4];

var max=Math.max.apply(Math,arr);

3.bind方法

fun.bind(thisArg,arg1,arg2...)

thisArg:在fun函数运行时指定的this值

arg:传递的其他参数

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

因此当我们只是想改变this指向,并且不想调用这个函数的时候可以使用bind

call,apply,bind总结

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

区别:call和apply会调用函数,且改变函数内部this指向,

call和apply传递参数不一样,后者是数组形式,bind不会调用函数

应用场景:call-继承

aplly-与数组有关,求最大值最小值

bind-改变定时器内部this指向

严格模式

'use strict'

1.为脚本开启严格模式

(function () {

  'use strict';

})();

2.为函数开启严格模式

严格模式中的变化

1.变量规定-在正常模式下,一个变量不声明就赋值,默认是全局变量,严格模式下禁止这种用法,变量必须才用var命令声明,然后再使用。

严禁删除已经声明的变量。例如delete x;语法是错误的。

2.严格模式下this指向问题

以往全局作用域函数中的this指向window对象。严格模式下全局作用域函数中的this是undefined。以前构造函数时不加new也可以调用,当普通函数,this指向全局对象。严格模式下,如果构造函数不加new调用,this指向的是undefined,如果给他赋值则会报错。

new实例化的构造函数指向创建的对象实例。

定时器this还是指向window。事件、对象还是指向调用者。

3.函数变化

函数不能有重名参数。

函数必须声明在顶层,新版本js会引入块级作用域,为了与新版本接轨,不允许在非函数的代码块内声明函数。

高阶函数:是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。

闭包:有权访问另一个函数作用域中变量的函数。就是一个作用域可以访问另一个函数内部的局部变量。

闭包的作用-延伸变量的作用范围。

闭包案例:打车价格

递归,一个函数在内部调用其本身,那个这个函数就是递归函数。递归函数的作用和循环效果一样。递归容易发生栈溢出,所以必须要加return退出条件。

递归案例:

求1-n的阶乘

求斐波那契数列

function fb(n) {

  if( n===1 || n=== 2){

      return 1;

}

return fb(n-1)+fb(n-2);

}

根据id返回对应的数据对象。

浅拷贝只拷贝一层,更深层次对象级别的只拷贝引用。

深拷贝拷贝多层,每一级别的数据都会拷贝。

Object.assign(target,...sources) es6新增方法可以浅拷贝

深拷贝封装

function deepCopy(newobj,oldobj) {

    for(var k in oldobj){

        var item = oldobj[k];

        if (item instanceof Array) {

            newobj[k] = [];

            deepCopy(newobj[k],item);

        } else if (item instanceof Object){

            newobj[k] = {};

            deepCopy(newobj[k],item);

        } else {

            newobj[k] = item;

        }

    }

}

你可能感兴趣的:(Js进阶)