码迷,mamicode.com
首页 > Web开发 > 详细

js 高级

时间:2018-09-28 22:38:41      阅读:250      评论:0      收藏:0      [点我收藏+]

标签:接口   继承   efi   length   inner   bin   function   第一个   myarray   

面向对象

封装

将功能封装整合在对象内, 只对外界暴露指定的接口, 外界只需要考虑接口怎么用, 而不需要考虑内部的具体实现

原型的引入

构造函数! 的prototype

每声明一个构造函数, 系统内部就会帮我们自动生成一个与之对应的原型对象

1. 构造函数 
function Student(){
    this.name = name;
    this.age = age;
    this.sayHi = function () {
        console.log("我的名字是"+this.name+",我的年龄是"+this.age);
    }
}
// 问题: 函数方法写在构造函数中,占用空间

2. 提取 构造函数的方法
function sayHi() {
    console.log("我的名字是"+this.name+",我的年龄是"+this.age);
}

function Student(){
    this.name = name;
    this.age = age;
    this.sayHi = sayHi
}
// 问题: 多个构造函数同时提出,造成命名冲突,以及全局变量污染

3. 对象 存放提取出来的方法
var tool = {
    sayHi:function () {
        console.log("我的名字是"+this.name+",我的年龄是"+this.age);
    }
}

function Student(){
    this.name = name;
    this.age = age;
    this.sayHi = tool.sayHi
}
// 问题: 每写一个构造函数,都要写一个对象,有没有统一的存放地呢?

4. 原型 prototype
function Student(){
    this.name = name;
    this.age = age;
}

Student.prototype.sayHi = function () {
    console.log("我的名字是"+this.name+",我的年龄是"+this.age);
}
// 那么: 所有的由 Student构造函数创建的 实例化对象们

使用原型的注意事项

1. 共有的数据才应该放入构造函数的原型中

2. 现在自己的原型中找,找不到就去构造函数的原型中找

3. 访问和使用原型,必须通过 prototype 属性

4. 修改原型前后,创建的实例化对象,所访问的原型是不同的

function Person(name,age){
    this.name = name;
    this.age = age;
}

Person.prototype.sayHi = function () {
    console.log("你好,我叫"+this.name+"你吃了吗...");
}

//实例化对象1
var p1 = new Person(‘全班第四‘,38);
p1.sayHi();

//修改原型 -------------------
Person.prototype = {
    sayHi: function () {
        console.log("我是修改后的原型中的sayHi方法....");
    }
}

//实例化对象2
var p2 = new Person(‘熊大‘,18);
p2.sayHi();
p1.sayHi()

实例化对象! 的 proto

__proto__ : 指向,实例化对象,的构造函数的 原型
function Student(name){
    this.name = name
}
Student.prototype.age = this.name

s1 = new Student("wang")

console.log(s1.age) // "wang"
s1.__proto__ == Student.prototype // true

原型对象! 的 constructor

constructor : 指向,原型的 归属 => 唯一对应的构造函数
function Student(name){
    this.name = name
}
Student.prototype.age = this.name

s1 = new Student("wang")

console.log(s1.age) // "wang"
s1.__proto__ == Student.prototype // true

继承

javaScript 中的继承, 就是对象之间的继承, 如果想要一个对象,拥有另一个对象的成员,就让这个对象继承另一个对象

继承的方法

for...in...

// for(var key in obj){
    key // 对象中的,键   
    obj[key] // 对象中的,值
}

var a = {
    house : "海景房",
    car : "兰博基尼",
    play:function(){
        console.log(this.house + this.car)
    }
}

var b = {
    name : "王思聪"
}

for(var key in a){
    b[key] = a[key]
}

console.log(b)

替换原型

// 会导致原有的原型丢失

var a = {
    house : "海景房",
    car : "兰博基尼",
    play:function(){
        console.log(this.house + this.car)
    }
}

var b = {
    name : "王思聪"
}
b.prototype = a

混合式 (对原型使用 for...in...)

var a = {
    house : "海景房",
    car : "兰博基尼",
    play:function(){
        console.log(this.house + this.car)
    }
}

var b = {
    name : "王思聪"
}

for(var key in a){
    // 给原型中添加 key,而不会覆盖原有的原型
    b.prototype[key] = a[key]
}

console.log(b)

多态

javascript 中, 没有多态

原型链

每一个对象, 都有自己的原型指向,原型本身也是一个对象,那么原型又有另一个原型指向,这样就形成了一个连式结构,称为原型链

对象属性

Obj.hasOwnProperty(‘属性名‘)

// 检测该对象, 是否拥有某个属性

var a = {
    house : "海景房",
    car : "兰博基尼",
    play:function(){
        console.log(this.house + this.car)
    }
}

a.hasOwnproperty(‘house‘)

Obj1.isPrototypeOf(obj2)

// obj1 是否为 obj2 的原型

var a = {
    house : "海景房",
    car : "兰博基尼",
    play:function(){
        console.log(this.house + this.car)
    }
}

Object.isPrototypeOf(a) // false
Object.prototype.isPrototypeOf(a) // true

obj instanceof 构造函数

var arr = [10,20,30];

arr instanceof  Array // true
arr instanceof  Object // true

在构造函数的原型中添加方法

// 问题: 给构造函数直接添加方法
// 所有成员都可以访问, 不安全, 在中间做一层
function myArray(){
    
}

myArray.prototype = []

// [] 空数组本身继承了,Array的原型中的所有方法和属性
// 所以 myArray 也就有了所有原型中的方法

Function() 实例化构造函数

1. 实例化一个函数
var test1 = new Function()
// 基本的函数功能
console.dir(test1)

2. 实例化,带有函数体的函数
var test2 = new Function(‘console.log("Function实例化的函数")‘)
// 带有属于自己的 函数体
console.dir(test2)

3. 实例化,带有参数和函数体的函数
var test3 = new Function(‘a‘,‘b‘,‘console.log(a + ":" + b)‘)
// 带有自己的参数 和 函数体
console.dir(test3)

函数对象中常用的属性

1. console.log()

2. new 

3. console.dir()

4. name

5. length

6. arguments
// arguments的caller是自己

7. caller 
// 在另外一个函数x中调用了我,我的caller就是那个函数x
// 直接调用我, 就是null

构造函数也是一个对象

1. 可以往构造函数中添加成员

2. 构造函数是由函数创建出来的

完整的原型链

画图

静态成员 & 实例成员

静态成员: 构造函数的成员
    构造函数.成员

实例成员: 实例化对象的成员
    实例化对象.成员

递归

1. 直接调用自己
function test (){
    let i = 0
    if(i < 50){
        test()   
        i++
    }
}

2. 间接调用自己
function test1(){
    let i = 0
    if(i < 30){
        test2()
        i++
    }
}

function test2(){
    test1()
}

// 应该要有结束的位置

递归求和

function get(n) {
    if (n == 1) {
        return 1
    }
    return n + get(n - 1)
}
var sum = get(5)

闭包

手动调用

// 函数内部的函数,形成闭包
function test1(){
    let name = "ts"
    function test2(){
        console.log(name)
    }
    return test2
}

const fn = test1()
fn()

自执行

var fn = (function () {
    var num = 10;

    function inner(){
        console.log(num);
    }

    return inner;
}());
//由于上面是一个自执行函数,不需要手动调用就会执行,得到一个返回值fn就是inner函数本身.
fn();

调用 & 赋值

function voter(){
    var num = 10;

    function add(){
        num++;
        console.log(num);
    }

    return add;
}

//2.1 相当于给一台投票机投了三张票.
var fn = voter(); //调用这个voter()函数,就会得到一个返回值fn,这个fn就相当于add函数.
fn();//11
fn();//12
fn();//13

//2.2 相当于给三台投票机每一台分别投了一张票.
voter()();
voter()();
voter()();

作用域问题

被闭包引用的变量会像全局变量一样,只有页面被关闭才会被销毁

内存泄露

当拥有特权的变量过多, 就会造成内存泄露

有限的访问权限

function getInfo(){
    name = "zhang3"
    age = 13
    function test1(){
        console.log(name)     
    }
    function test2(){
        console.log(age)
    }
    return {
        getName:test1
        getAge:test2
    }
}

var user = getInfo()
user.getName()
user.getAge()

沙箱

(function ($){
    $.name= "shangsan"
    $.age = 14
})(window)

函数的上下文调用

函数的三种调用

  1. 函数调用
  2. 方法调用
  3. 构造函数调用

call() - 执行,参数不限

// 修改当前函数内的指向, 

const obj = {
    name : "xiaoming"
}

function change(name){
    this.name = name
    console.log(this.name)
}

// 并无限传参
change.call(obj,"小丽")

apply() - 执行,参数唯一[]

// 修改当前函数内的指向, 

const obj = {
    name : "xiaoming"
}

function change(name){
    this.name = name
    console.log(this.name)
}

// 参数唯一: 数组[元素,分别传入]
change.apply(obj,["小丽"])

bind() - 不执行,返回函数

// 返回修改指向,后的函数
const obj = {
    name : "xiaoming"
}

function change(name){
    this.name = name
    console.log(this.name)
    return this
}

// 参数唯一: 数组[元素,分别传入]
let newChange = change.bind(obj,"小丽")
newChange()

三个方法的特性

  1. 所有函数都可以用
    三个修改上下文的方法, 都在 Function.prototype 上
  2. 第一个参数决定指向
    function test1(){
    console.log(this);
    }
    test1.call(123); // Number
    test1.call("abc"); // String
    test1.call(true); // Boolean
    test1.call(null); // Window
    test1.call(undefined); // Window
    test1.call(); // Window
    test1.call(window); // Window
  3. 只有使用了方法的函数指向会发生变化
    var obj = {
    name : "san"
    }

    function change(){
        console.log(this) // obj
        function test(){
            console.log(this) // window
        }
        test()
    }
    
    change.call(obj)

正则

预定义类

.   [^\r\n]   非换行 和 回车

\d  [0-9]   数字
\D  [^0-9]  非数字

\s  []  不可见
\S  []  可见

\w  [a-zA-Z0-9_]    单词字符[所有字母+数字+_]
\W  [^a-zA-Z0-9_]   非单词字符[字母 + 数字 + _]

// 修饰符
g   全局匹配
i   忽略大小写

gi  全局匹配 + 忽略大小写

自定义类 /abc/

/s(a||b)ve/ // (优先级提升)  save || sbve 即可

简单类 /[]/

/[abc]/ // 只要含有 a || b || c 的就行, 匹配1个字符

负向类 /[^abc]/

/[^]/   // 必须在简单类中, 用^开头, 才表示负向
/[^abc]/    // 包含非 abc 的存在  

范围类/[0-9]/

/[0-9]/   // 指定一个范围内的匹配

组合类

/[a-m1-5\n]/    // 匹配 a-m || 1-5 || \n

/[^0-5][^a-g]/    // 匹配两个字符的组合, 第一个非0-5, 第二个非 a-g

严格匹配

/^afwef/  //a开头 + 完整显示一次 afwef; 

/afwef$/    // f结尾 + 完整显示一次 afwef;

/^ $/   //以什么开头, 以什么结尾
/^a[\w]b$/  // afb acb; 必须是 a开头,中间1位,b结尾 的模式

量词 * + ?

*   0 || 多次     == {0,}
/ab*c/  // abc , abbbc, ac;  b可以重复 0次 或 多次
    
+   1 || 多次     == {1,}
/ab+c/  // abc , abbbc;  b可以重复 0次 或 多次

?   0 || 1      == {0,1}
/ab?c/  // abc , ac;  b只能是 0次 或 1次

汉字

// js 中, 使用 Unicode 编码汉字

// 转码
escape("汉字") => Unicode 编码

unescape("%u6C49%u5B57") => 汉字

//  所有汉字的范围     \u4e00-\u9fa5
/[\u4e00-\u9fa5]/
  

替换 str.replace + 正则

var str = "a100b200c30d50";

// replace 替换, 
// 参数1: 正则 / 字符
// 参数2: 被替换项
str.replace(/\d/,"B")   // 将 第一个 数字转换为B

str.replace(/\d/g,"B")  // 将 所有 数字转换为B

提取 str.match + 正则

let str = "123123@xx.com,penglin@163.com.cn";
let reg = /(\w+)@(\w+)\.(\w+)(\.\w+)?/g;
let array = str.match(reg);

检索 str.search + 正则

let str = "abcd1000ef2000g5000";
let idx = str.search(/\d/)

分割 str.split + 正则

let str = "张三100李四200王五";
let arr = str.split(/\d{3}/)

js 高级

标签:接口   继承   efi   length   inner   bin   function   第一个   myarray   

原文地址:https://www.cnblogs.com/cubo/p/9721282.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!