面向对象编程及原型链,正则表达式

本文详细介绍了JavaScript中的面向对象编程,包括创建对象的方法、成员类型、构造函数的问题及原型链的原理。同时,文章探讨了this关键字的使用及其在不同场景下的指向。此外,还深入讲解了正则表达式的创建、字符串相关方法以及正则的组成部分和修饰符。
摘要由CSDN通过智能技术生成

一.面向对象编程

1.创建对象方法

1.1简单方式

    var person = new Object();
    person.name = "Bob";
    person.age = 18;
    person.sayName = function () {
      console.log(this.name);
    };
    person.sayName();

1.2对象字面量化简

    var person1 = {
      name : "Bob",
      age : 18,
      sayName : function () {
        console.log(this.name);
      }
    };
    var person2 = {
      name : "Mike",
      age : 20,
      sayName : function () {
        console.log(this.name);
      }
    };
    person1.sayName();
    person2.sayName();

1.3工厂函数

    function createPerson(name,age) {
      // 添加一个新对象
      var person = new Object();
      person.name = name;
      person.age = age;
      person.sayName = function () {
        console.log(this.name);
      };
      // 必须有返回值
      return person;
    }
    // 生成真正的对象
    var person1 = createPerson("John",19);
    var person2 = createPerson("Mike",18);
    person1.sayName();

1.4自定义构造函数

    function Person(name,age) {
    //1.创建一个新对象
        //var instance = new Object();
    2.将函数内部的 this 指向了这个新对象 
        //this = instance;
    // 3.执行构造函数内部的代码
        this.name = name;
        this.age = age;
        this.sayName = function() {
            conosole.log(this.name);
        };
    //4.将新对象作为返回值
        return instance ;
    }
    Person.version = "1.0"//定义静态成员
    var person1 = new Person("zs",16);
    var person2 = new Person("ls",15);
    person1.sayName();

new 关键字的用途
1.创建一个新对象
2.将函数内部的 this 指向了这个新对象
3.执行构造函数内部的代码
4.将新对象作为返回值

  • 用instanceof判断一个对象的具体对象类型

1.5总结:如果对象不需要生成实例可以直接使用字面量方式封装,不需要使用构造函数封装

2.成员

2.1 静态成员

添加给构造函数自身的成员,只能用构造函数调用,不能使用生成的实例对象调用

//调用自定义构造函数代码
console.log(Person.name)//使用构造函数调用实例成员会出错
console.log(Person.version)//可以正常调用静态成员

2.2实例成员

构造函数内部添加给this的成员,属于实例对象的成员,在创建对象后必须由对象调用

//调用自定义构造函数代码
conosle.log(person1.name)//调用实例成员
conosle.log(person1.version)//undefined

3.构造函数存在的问题

  1. 内存浪费
    解决方案:利用原型对象(prototype)
    任何函数都有protype属性,属性值时一个对象。内部可以添加属性和方法,原型对象所有的属性和方法都会被构造的实例对象拥有 Person.prototype.type = "human"
console.log(Person.prototype);//指向原型对象
conosle.log(person1.__proto__);//指向原型对象
console.log(Person.prototype.constructor);//指
向构造函数   
console.log(person1.constructor)//指向构造函数 

所有的对象都有一个 -proto- 的属性,是一个指针,指向的就是生成实例对象的 构造函数的原型对象

4.原型链

任何一个对象都有 proto 属性,指向的就是该对象的 构造函数的原型对象。 当调用一个对象的方法时,如果对象没有该方法就沿原型链向上查找直到null。

4.1实例对象读写原型对象成员

  1. 通过实例对象添加新成员,会直接添加给自己,会屏蔽掉对原型对象的访问
    person1.sex = "male";
    person1.sayAge = function () {
      console.log(this.age);
    };
  1. 如果通过实例对象更改简单类型原型对象的属性和方法,会直接添加给自己,会屏蔽掉对原型对象的访问
    person1.type = "person";
    person1.sayName = function () {
      console.log(this.name);
    }
    console.dir(person1);
  1. 通过实例对象更改原型对象中复杂类型数据中的内容.如果自身有该成员就直接修改,如果没有还是会进行原型链的查找
    person1.address.city = "上海";
  2. 简化书写
    为了避免重复书写原型对象和实例对象,可将包含所有属性和方法的对象字面量来重写整个原型对象。但是会丢失constructor成员,需要手动将constructor指向正确的构造函数。
    私有成员(一般为非函数成员)设置在构造函数中。
    公有成员(函数成员)放置到原型对象中。
    重置了protype需要修正constrctor指向。

4.2this关键字

总结:不同函数内部this指向
全局执行上下文中的this指向的是windwo对象;普通函数中this指向window对象;构造函数中this指向生成的实例对象;对象的方法中的this指向对象本身;事件函数中的this指向事件源。
执行上下文分为:全局执行上下文、函数执行上下文、eval执行上下文,所以对应的this也由三种。

通过构造函数方式定义函数

 var fun = new Function('var a = "1"; console.log(1)');
 fun();

4.3修改this指向的方法

4.3.1 call方法

功能:1.指定函数的this   2.执行函数并传参
参数:1.指定让this指向的对象 第二个及以后参数是函数参数的列表
返回值:函数自己的返回值
fun.call(o,1,2);
call的应用:处理对象时借用其他对象的方法

    var o ={
        0:10;
        1:20
        lenght:2
    }
    //利用数组中的push方法,指定内部的this为对象o,就可以处理类数组对象
    Array.prototype.push.call(o,50);
    console.log(o);
4.3.2 apply方法

功能:1.指定函数的this   2.执行函数并传参
参数:1.指定让this指向的对象 第二个参数是函数参数的列表
返回值:函数自己的返回值
fun.apply(o,[4,5]);
apply方法的应用:将数组作为参数传入

 var   arr = [1,2,3,6,8];
//利用apply方法将数组传给了max的第二个参数
 Math.max.apply(null,arr);//null指不改变原来的this指向
4.3.3 bind方法

功能:指定函数的this &emsp 2.不能执行函数但可传参
参数:1.传入让this指向的对象,第二个及以后是函数参数的列表
返回值:返回一个新的指定了this的函数

    var fn = fun.blid(o,2,3); //传参不执行
    fn(5,9);   //执行函数时,将绑定函数和执行函数的参数都作为实参传入。将参数拆开传入

bind方法的应用;定时器或事件函数

  var o = {
      name: "zs";
      age : 18;
      s: function () {
        setInterval (function () {
            console.log(this.age);
        },500);
  }
  o.s();//结果是undefinde
  //更改定时器中的this
    var o = {
      name: "zs";
      age : 18;
      s: function () {
        setInterval (function () {
            console.log(this.age);
        }.bind(this),500);
  }
  o.s();// 结果输出18
  

注:通过自调用函数,进行封装。通过window暴露 Food对象
window.Food = Food (function(){})();

4.4 this中的缺陷

4.4.1 嵌套函数中的this不会从外层函数中继承
var myObj = {
  name : "zs", 
  showThis: function(){
    console.log(this)
    function bar(){console.log(this)}
    bar()
  }
}
myObj.showThis()

showThis方法里的this指向的是myObj对象,但是bar函数中的this指向的是window对象。
解决方法:方法一:在showThis函数中声明一个that变量保存this (将this体系转换为作用域的体系)
方法二:使用箭头函数

var myObj = {
  name : "zs", 
  showThis: function(){
    console.log(this)
    var bar = () =>{
	this.name = "ls"
	console.log(this)}
    bar()
  }
}
myObj.showThis()		//{name: "zs", showThis: ƒ}
console.log(myObj.name) //{name: "ls", showThis: ƒ}
console.log(window.name)//ls
4.4.2 this指向(在调用时确定具体指向)

普通函数:this默认指向window
构造函数:内部this指向将来创建的实例对象
对象中的方法:内部this默认指向调用的对象自己
事件函数:this指向触发事件的事件源 app.onclick = function() {console.log(this)} this指向的是app
定时器和延时器函数:内部this指向window

二、继承

1.call方法 :执行函数的方法

1.在调用函数时可以更改函数的内部指向
2.调用函数执行内部代码
参数:第一个参数指定this指向,第二个参数是传入的实参

//借用构造函数继承
function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype.sayHi = function (){ //方法也需要继承
    console.log("nihao");
}
function Student(name,age,score){
      Person.call(this,name,age);
      this.score = score;
}
//继承方法的方法1:对象拷贝继承
for(var k in Person .prototype){
//保留constructor不需要继承
if(k==="constructor"){continue;}
  Student.prototype[k] = Person.prototype[k];
}
//方法2:原型继承
Student.prototype = new Person();
Student.prototype.constructor = Student ;//保证constructor指向正确
var s1 = new Student("zs","13","75");
      s1.sayHi();

2.组合继承 :属性在构造函数内部继承,方法通过原型继承

3.函数中的其他成员

arguments属性是传入所有实参组成的一个类数组对象
argument.callee函数本身,arguments的一个属性
caller 函数的调用者,函数在哪个作用域调用,caller就是谁,全局为null
length指的是形参的个数
name指的是函数的名字
高阶函数:作为参数或返回值的函数

三.正则表达式

在JS中的正则表达式是一种索引类型,也是对象

\s 空白  \d数字

3.1创建正则表达式

1.var reg = /abc/; 2.var reg = newRegExp("abc");
正则表达式字面量在脚本加载后编译,性能更好

3.2字符串方法

  1. split() 分割字符串为数组
var str = "aa  bbb     ccd  e";
//var arr = str.split(" "); //以空格作为分隔符
console.log(arr); //空字符串也会被分割到数组中
//使用正则表达式可以进行模糊匹配分割
 var arr1 = str.split(/\s+/); //以多个空白作为分隔符
console.log(arr); //空字符串会被自动过滤
  1. search方法:寻找匹配字符串在父字符串中的位置
var str = "abaaacsaaaa";
console.log(str.search("cd")); //输出结果为5
console.log(str.search(/cd/);//输出结果为5
  1. match()方法:在父字符串中寻找匹配字符串结果输入到数组中
var str = "abaafbfefefebdsljk";
var arr = str.match(/b+/);
console.log(arr); //在匹配到第一个字符串就结束
var arr1 =str.match(/b+/g);//如果有全局修饰符g,会找所有匹配的字符串后结束 
console.log(arr1);
  1. replace方法:替换父字符串中匹配的字符串,返回新的替换后的字符串,原始字符串不受影响
var str = "www.hello.com";
var str1 = str.replace(/hello/,"byebye");
console.log(str);  //www.hello.com
console.log(str1); //www.byebye.com

3.3正则表达式方法

  1. exec 查找匹配的字符串,输出到数组中。不论有没有全局修饰符,都会只找到第一个后停止
var str = "aaaavvvccc";
var reg = /av/;
var arr = reg.exec(str);
console.log(arr);	//Array(1)对象
  1. test方法:匹配字符串是否符合正则表达式(返回值为Boolean类型)
var reg =/abc/;
console.log(reg.test("5661abcdsf")); //true

3.4正则表达式的组成

  1. 特殊字符
    \t 制表符
    \n 回车符
    \f 换页符
    \b 空格
var str = `sdfsfsf
eoffjf`
console.log(/\n/.test(str));

2.字符集:使用[ ]表示的可能字符的集合,吉和内部可以排列多个匹配字符串的可能性,整个字符集需要匹配的是字符串中的一个字符
2.1 简单类:多个可能匹配的字符连续书写在一起,只要其中一个匹配成功即可

var reg = /[abc]/;
console..log(reg.test("efefabc"));//true

2.2 范围类:匹配过多简化操作[a-z]、[0-9]、[A-Z]
2.3 反向类:去反,表示不能匹配括号里的字符.[^a] [^a-q]
2.4 组合类:单一类或者简单类不可匹配所有结果,可以将多个写法连在一起书写[0-9a-z]、0-Z

3.5修饰符

  1. g 全局查找
var str = "adafdsdfdasfaaa";
var reg = /b+/g;
console.log(str.match(reg));
  1. i修饰符:字母大小写不敏感 ,a可以匹配A
var str = "adafdsdfdasfBBBaaa";
var reg = /b+/A;
console.log(str.match(reg));
  1. 边界

^开头 不可跟在中括号后面
/^hello/

结 尾 : 前 面 的 正 则 内 容 匹 配 的 结 果 必 须 出 现 在 字 符 串 结 尾 / a a a 结尾:前面的正则内容匹配的结果必须出现在字符串结尾 /aaa :/aaa/

3.6 预定义类

.  	 [^\n\r] 除了换行和回车的任意字符
\d	[0-9]	数字字符
\D	[^0-9]	非数字字符	
\s	[\t\n\x0B\f\r]	空白字符
\S	[^\t\n\x0B\f\r]	非空白字符
\w	[a-zA-Z_0-9]	单词字符(所有的字母数字下划线)
\W	[^a-zA-Z_0-9]	非单词字符

3.7量词

{n} 硬性量词 对应前面的内容必须在字符串中出现n次连续
{n,m} 弹性量词 对应前面的内容必须在字符串中出现 n~m 次连续
{n,} 弹性量词 对应前面的内容必须在字符串中至少出现n次连续
? 弹性量词 表示前面的内容出现0次或者1次
‘*’ 弹性量词 表示前面的内容出现任意次
‘+’ 弹性量词 表示前面的内容出现至少1次

var reg = /^\d{5}/;
var reg = /^\d{5,7}/;
  • 分组
    /^(bye){2}/
    或操作符|
    /a|bcd/
//在正则中过两个规则只能选自一种,不能包含其他的开头结尾,需要去将运算放在分组里
var reg = /^(ad|cd)$/;

分组的反向:使用匹配到的字符作为条件匹配其他字符

  • 内部引用 (用\次数表示)
console.log(/^([a-z]{3})\2$/.test("byebyebye"));//true 把满足条件的前三个字母作为条件来匹配剩余字符
console.log(/^([a-z]{3})\2$/.test("byebyebie"));//false
  • 外部引用 (用$编号表示)
var str = 123*456.replace(/^(\d{3})\*(\d{3})$/,"$2*$1");
  • 中文字符 [\u4e00 - \u9fa5]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值