你不知道的JavaScript---------- 行为委托

2023-10-29

目录

[[Prototype]]机制

面向委托的设计

类理论

委托理论 

比较思维模型 

JavaScript创建UI控件

控件创建渲染 (ES5类继承形式)

控件“类” (类形式)

 委托控件对象 (委托形式)

 更简洁的设计

更好的语法

内省


[[Prototype]]机制

[[Prototype]] 机制: JavaScript 中这个[[Prototype]] 机制的本质就是对象之间的关联关系。

面向委托的设计

类理论

SonA 未重写父类方法,所以.say()执行的是父类中的say方法

SonB 重写了父类方法,所以.say()执行的是重写后的say方法

class Father {
    id = '';
    constructor(id) {
        this.id = id;
    }
    say() {
        return this.id;
    }
}

class SonA extends Father {
    label = '';
    constructor(id, label) {
        super(id);
        this.label = label;
    }
}

class SonB extends Father {
    label = '';
    constructor(id, label) {
        super(id);
        this.label = label;
    }
    say() {
        return this.label;
    }
}

const sonA = new SonA('aaa', 'Lee');
const sonB = new SonB('bbb', 'Tom');

console.log(sonA, sonB); // SonA {id: 'aaa', label: 'Lee'}  SonB {id: 'bbb', label: 'Tom'}
console.log(sonA.say(), sonB.say()); // aaa Tom

委托理论 

同样是把实例委托给了Bar并把Bar委托给了Foo,从而实现了三个对象之间的关联。但是这里更简洁,不需要那些复杂困惑的模仿类行为,比如构造函数、原型以及new

  • 通常来说,在[[Prototype]]委托中最好把状态保存在委托者 而不是委托目标上;
  • 在委托行为中,会尽量避免在[[Prototype]]链的不同级别中使用相同的命名;
  • 委托行为意味着某些对象在找不到属性或者方法引用时会把这个请求委托给另一个对象。
        Foo = {
            init : function(who) {
                this.me = who;
            },
            identity : function() {
                return "I am " + this.me;
            }
        };

        Bar = Object.create(Foo); // 开始第一层委托

        Bar.speak = function() { // 定义自己的功能
            alert("Hello" + this.identity() + "."); // 把委托隐藏在 API 内部
        }


        var b1 = Object.create(Bar); // 开始第二层委托
        b1.init("Saul");


        var b2 = Object.create(Bar);
        b2.init("Carrie");

        b1.speak();
        b2.speak();

互相委托(禁止):​ 你无法在两个或两个以上互相(双向)委托的对象之间创建循环委托。

调试:​ 对象关联风格的代码中,不需要关注谁“构造了”对象,浏览器调试中“构造函数名称”的跟踪没有意义。

比较思维模型 

类理论

function Foo(who) {
       this.me = who;
}
Foo.prototype.identify = function() {
      return 'I am ' + this.me;
};

function Bar(who) {
      Foo.call(this, who);
}
Bar.prototype = Object.crreate(Foo.prototype);

Bar.prototype.speak = function() {
      alert('Hello, ' + this.identify() + '.');
};

var b1 = new Bar('b1');
var b2 = new Bar('b2');

b1.speak();
b2.speak();

 JavaScript中的函数之所以可以访问call(..)、apply(..)和bind(..),就是因为函数本身是对象,而函数对象同样有[[Prototype]]并且关联到Function.prototype对象,因此所有函数对象都可以通过委托调用这些默认方法。

var Foo = {
      init: function(who) {
           this.me = who;
      },
      identify: function() {
            return 'I am ' + this.me;
      }
};
var Bar = Object.create(Foo);

Bar.speak = function() {
      alert('Hello, ' + this.identify() + '.');
};

var b1 = Object.create(Bar);
b1.init('b1');
var b2 = Object.create(Bar);
b2.init('b2');

b1.speak();
b2.speak();

JavaScript创建UI控件

控件创建渲染 (ES5类继承形式)

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.slim.min.js"></script>
<script>
    // 控件基类 宽 高 元素
    function Widget(width, height) {
        this.width = width || 50;
        this.height = height || 50;
        this.$elem = null;
    }

    // 渲染方法
    Widget.prototype.render = function ($where) {
        // 在元素结尾插入元素
        if (this.$elem) {
            this.$elem.css({
                width: this.width + "px",
                height: this.height + "px"
            }).appendTo($where);
        }
    };

    // Button控件
    function Button(width, height, label) {
        // 调用“super”构造函数 
        Widget.call(this, width, height);
        this.label = label || "Default";
        this.$elem = $("<button>").text(this.label);
    }

    // 让 Button“继承”Widget
    Button.prototype = Object.create(Widget.prototype);

    // 重写 render(..)
    Button.prototype.render = function ($where) {
        //“super”调用
        Widget.prototype.render.call(this, $where);
        this.$elem.click(this.onClick.bind(this));
    };

    // Button点击事件
    Button.prototype.onClick = function (e) {
        alert(`Button ${this.label} clicked!`);
    };

    $(document).ready(function () {
        var $body = $(document.body);
        var btn1 = new Button(125, 30, "Hello");
        var btn2 = new Button(150, 40, "World");
        btn1.render($body);
        btn2.render($body);
    });

控件“类” (类形式)

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.slim.min.js"></script>
<script>
    // UI组件基类
    class Widget {

        /**
         * 初始化控件
         * @param {number} width 宽度
         * @param {number} height 高度
         * @returns {undefined}
         */
        constructor(width, height) {
            this.width = width || 50;
            this.height = height || 50;
            this.$elem = null;
        }

        /**
         * 渲染控件
         * @param {Element} $where 父控件
         * @returns {undefined}
         */
        render($where) {
            if (this.$elem) {
                this.$elem.css({
                    width: this.width + "px",
                    height: this.height + "px"
                }).appendTo($where);
            }
        }

    }

    // Button组件
    class Button extends Widget {

        /**
         * 初始化控件
         * @param {number} width 宽度
         * @param {number} height 高度
         * @param {string} label 控件内容
         * @returns {undefined}
         */
        constructor(width, height, label) {
            // 调用父类方法
            super(width, height);
            this.label = label || "Default";
            this.$elem = $("<button>").text(this.label);
        }

        /**
         * 渲染控件 重写父类方法
         * @param {Element} $where 父控件
         * @returns {undefined}
         */
        render($where) {
            super.render($where);
            this.$elem.click(this.onClick.bind(this));
        }

        // 点击事件
        onClick(e) {
            alert(`Button ${this.label} clicked!`);
        }
    }

    // 添加UI组件
    $(document).ready(function () {
        var $body = $(document.body);
        var btn1 = new Button(125, 30, "Hello");
        var btn2 = new Button(150, 40, "World");
        btn1.render($body);
        btn2.render($body);
    });

 委托控件对象 (委托形式)

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.slim.min.js"></script>
<script>
    // UI控件基类
    var Widget = {
        init: function (width, height) {
            this.width = width || 50;
            this.height = height || 50;
            this.$elem = null;
        },
        insert: function ($where) {
            if (this.$elem) {
                this.$elem.css({
                    width: this.width + "px",
                    height: this.height + "px"
                }).appendTo($where);
            }
        }
    };

    // Button继承自Widget
    var Button = Object.create(Widget);

    // Button控件初始化
    Button.setup = function (width, height, label) {
        // 委托调用
        this.init(width, height);
        this.label = label || "Default";
        this.$elem = $("<button>").text(this.label);
    };

    // Button控件创建
    Button.build = function ($where) {
        // 委托调用
        this.insert($where);
        this.$elem.click(this.onClick.bind(this));
    };

    // Button点击事件创建
    Button.onClick = function (e) {
        alert(`Button ${this.label} clicked!`);
    };


    $(document).ready(function () {
        var $body = $(document.body);

        var btn1 = Object.create(Button);
        btn1.setup(125, 30, "Hello");

        var btn2 = Object.create(Button);
        btn2.setup(150, 40, "World");

        btn1.build($body);
        btn2.build($body);
    });

 更简洁的设计

看个例子,我们有两个控制器对象,一个用来操作网页中的登录表单,另一个用来与服务器进行通信。

mock数据        

{
    "code": 200,
    "data": {
        "name": "PLee",
        "age": 18
    },
    "msg": "操作成功"
}

 在传统的类设计模式中,我们会把基础的函数定义在名为Controller的类中,然后派生两个子类LoginController和AuthController,它们都继承自Controller并且重写了一些基础行为:

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
<script>
    // 基类
    class Controller {

        errors = null;

        constructor() {
            this.errors = [];
        }

        // 获取得到的数据
        getData(title, data) {
            console.log(title, data);
        }

        // 成功
        success(res) {
            this.getData("【Success】", res);
        }

        // 失败
        failure(err) {
            this.errors.push(err);
            this.getData("【Error】", err);
        }

    }

    // 登录
    class LoginController extends Controller {

        constructor() {
            super();
        }

        // 获取用户名
        getUser() {
            return document.getElementById("login_username").value;
        }

        // 获取密码
        getPassword() {
            return document.getElementById("login_password").value;
        }

        // 验证 用户名/密码
        validateEntry(user, pw) {
            user = user || this.getUser();
            pw = pw || this.getPassword();
            if (!user) {
                return this.failure("请输入用户名!");
            }
            if (!pw) {
                return this.failure("请输入密码!");
            }
            // 如果执行到这里说明通过验证
            return true;
        }

        // 重写基础的 failure()
        failure(err) {
            super.failure(err);
        }

    }

    // 认证
    class AuthController extends Controller {

        login = null;

        constructor(login) {
            super();
            this.login = login;
        }

        // 数据请求
        server(url, data) {
            return $.ajax({ url, data });
        }

        // 检查认证
        checkAuth() {
            var user = this.login.getUser();
            var pw = this.login.getPassword();
            if (this.login.validateEntry(user, pw)) {
                this.server("/check-auth.json", { user, pw })
                    .then(res => this.success(res))
                    .fail(err => this.failure(err));
            }
        }

        // 成功
        success(res) {
            super.success(res);
        }

        // 失败
        failure(err) {
            super.failure(err);
        }

    }

    $(document).ready(function () {
        $('#login_btn').click(function (e) {
            var auth = new AuthController(new LoginController());
            auth.checkAuth();
        })
    })

使用对象关联风格的行为委托来实现:

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
<script>
    // 基础对象
    var LoginController = {
        errors: [],
        // 获取用户名
        getUser: function () {
            return document.getElementById('login_username').value;
        },
        // 获取密码
        getPassword: function () {
            return document.getElementById('login_password').value;
        },
        // 校验用户名密码
        validateEntry: function (user, pw) {
            var user = user || this.getUser();
            var pw = pw || this.getPassword();
            if (!(user && pw)) {
                return this.failure('Please enter a username & password!');
            } else if (pw.length < 5) {
                return this.failure('Password must be 5+ characters!');
            }
            return true;
        },
        // 相应结果
        showDialog: function (title, msg) {
            //给用户显示标题和消息
            console.log(title, msg);
        },
        // 失败
        failure: function (err) {
            this.errors.push(err);
            this.showDialog('Error', 'Login invalid:' + err);
        }
    }
    // 登录对象
    //让AuthController委托LoginController
    var AuthController = Object.create(LoginController);

    AuthController.errors = [];

    // 登录
    AuthController.checkAuth = function () {
        var user = this.getUser();
        var pw = this.getPassword();
        if (this.validateEntry(user, pw)) {
            this.server("/check-auth.json", { user, pw })
                .then(res => this.accepted(res))
                .fail(err => this.rejected(err));
        }

    }
    // 发送请求
    AuthController.server = function (url, data) {
        return $.ajax({
            url: url,
            data: data
        })
    }
    // 成功提示
    AuthController.accepted = function (res) {
        this.showDialog('Success', res);
    }
    //失败提示
    AuthController.rejected = function (err) {
        this.failure('Auth Failed:' + err);
    }
    // 登录事件
    $(document).ready(function () {
        $('#login_btn').click(function (e) {
            AuthController.checkAuth();
        })
    })

更好的语法

在ES6中我们可以在任意对象的字面形式中使用简洁方法声明:

匿名函数没有name标识符,会导致:

  • 1)调用栈更难追踪;
  • 2) 自我引用(递归、事件(解除)绑定等)更难;
  • 3)代码(稍微)更难理解。

简洁方法没有第1和第3个缺点,但是无法避免第2个缺点,如果需要自我引用,最好使用传统的具名函数表达式来定义对应的函数,不要使用简洁方法。

var LoginController = {
    errors: [],
    getUser(){//简洁方法
        //...
    },
    getPassword(){//简洁方法
        //...
    },
    //...
}
var AuthController = {
    errors: [],
    checkAuth(){//简洁方法
        //...
    },
    server(url, data){//简洁方法
        //...
    },
    //...
}
//把AuthController关联到LoginController
Object.setPrototypeOf(AuthController, LoginController);

内省

内省就是检查实例的类型。类实例的内省主要目的是通过创建方式来判断对象的结构和功能。

getPrototypeOf该方法返回指定对象的原型

isPrototypeOf返回一个布尔值,指出对象是否存在于另一个对象的原型链中。

instanceof运算符用来判断一个构造函数的prototype属性所指向的对象是否存在另外一个要检测对象的原型链上

    function Foo() {
        // ...
    }
    Foo.prototype.something = function () {
        // ...
    }
    var a1 = new Foo();
    // 之后
    if (a1 instanceof Foo) {
        a1.something();
    }

因为Foo.prototype(不是Foo!)在a1的[[Prototype]]链上

对于“类”设计风格,如果要使用instanceof和.prototype语义来检查本例中实体的关系,那必须这样做: 

    function Foo() {}
    function Bar() {}
    Bar.prototype = Object.create(Foo.prototype);
    var b1 = new Bar("b1");

    // 让Foo和Bar互相关联
    Bar.prototype instanceof Foo;// true
    Object.getPrototypeOf(Bar.prototype) === Foo.prototype;// true
    Foo.prototype.isPrototypeOf(Bar.prototype);// true

    // 让b1关联到Foo和Bar
    b1 instanceof Foo;// true
    b1 instanceof Bar;// true
    Object.getPrototypeOf(b1) === Bar.prototype;// true
    Foo.prototype.isPrototypeOf(b1);// true
    Bar.prototype.isPrototyoeOf(b1);// true

显然这是一种非常糟糕的方法。举例来说,(使用类时)你最直观的想法可能是使用Bar instanceof Foo(因为很容易把“实例”理解成“继承”),但是在JavaScript中这是行不通的,你必须使用Bar.prototype instanceof Foo。

instanceof 告诉我们左边要对象,右边要函数。Bar是函数,Bar.prototype是对象

使用对象关联时,所有的对象都是通过[[Prototype]]委托相互关联,下面是内省的方法:

var Foo = {/* .. */};

var Bar = Object.create(Foo);

var b1 = Object.create(Bar);
Foo.isPrototypeOf(b1);// true
Bar.isPrototypeOf(b1);// true
Object.getPrototypeOf(b1) === Bar;// true

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

你不知道的JavaScript---------- 行为委托 的相关文章

  • Jquery获取选中的复选框

    您好 我想获取页面中选定复选框的列表 实际上我真正需要的是获取复选框旁边的元素的文本 该元素是一个 html 元素 li 代码如下 但它不起作用 这是我当前的 jQuery document ready function target cl
  • 将 Javascript 对象的属性从 string 更改为 int

    我有一个对象数组 每个对象具有三个属性 年份 总计 人均 例子 0 Object per capita 125 8 total 1007 2 year 2009 这些属性是字符串 我想创建一个循环来遍历数组并将它们转换为 int 我尝试了以
  • Jquery 悬停卡

    我在用着http designwithpc com Plugins Hovercard http designwithpc com Plugins Hovercard 但我不知道如何在悬停卡上声明 var 每个工作描述都有自己的 ID 当悬
  • 从函数返回函数的目的是什么?

    阅读一些遗留代码 发现 A prototype setSize function var v1 new Vector2 return function size var halfSize v1 copy size multiplyScala
  • 位置特征检测:固定

    我正在尝试找到一个脚本来检测设备是否放置position fixed元素相对于视口而不是整个文档 目前 标准桌面浏览器和 Mobile Safari 适用于 iOS 5 都是这样做的 而 Android 设备则相对于整个文档放置固定元素 我
  • 在版本 4.4.6 中禁用 ckeditor 上下文菜单

    我在 Rails4 项目中使用 ckeditor 我尝试了 ckeditor gem 和 ckeditor rails gem 来提供 ckeditor 库 这里有多个帖子 人们希望删除 ckeditor 上下文菜单 以便可以显示本机浏览器
  • 为什么 window 与 Internet Explorer 中的 window.self 不同?

    关于我如何遇到这个问题有一个复杂的背景故事 但为什么self属性不完全等于窗口本身 在 Safari 和 Firefox 及其朋友中 结果如我所料 gt window window self true gt window window se
  • 如何在React Native Android中获取响应头?

    您好 我想在获取 POST 请求后获取响应标头 我尝试调试看看里面有什么response with console log response 我可以从以下位置获取响应机构responseData但我不知道如何获取标题 我想同时获得标题和正文
  • 导航栏下拉菜单(折叠)在 Bootstrap 5 中不起作用

    我在尝试使用以下命令创建响应式菜单或下拉按钮时遇到问题Bootstrap 5一切似乎都正常 导航图标和下拉图标出现 但它不起作用 当我单击nav图标或dropdown按钮 无dropdown menu apears 我想特别提到的是 我还包
  • 按下回车键时不刷新页面

    我遇到了一些问题 只要表单中有输入 回车键就会触发页面刷新 下面的代码 如果按下回车并且文本区域 input 中没有输入任何文本 则不会刷新页面 但是如果按下回车并且 input中有输入或者光标位于文本区域 我不确定是什么触发了它 因为 s
  • ReactTransitionGroup 不适用于 React-redux 连接组件

    我正在开发一个更大的项目 但我创建了这个简短的示例来说明问题 如果我使用Box组件 它的工作原理 它在控制台中输出componentWillEnter and componentWillLeave当我们点击按钮时 如果我使用BoxConta
  • 如何使用 Greasemonkey 监视静态 HTML 页面的更改?使用哈希?

    我希望我的 Greasemonkey 脚本仅在其访问的静态页面具有与以前完全相同的内容时运行 现在我可以设置一个包含该页面哈希的变量 我正在寻找一种动态散列页面的方法 以便我可以将我的散列与生成的散列进行比较 关于如何即时实现散列的任何想法
  • javascript 选择自定义光标 (svg)

    我正在动态地将光标更改为悬停时的本地 svg element on mouseover function this css cursor url svgs pointer svg 9 30 auto 工作正常 但我想选择该 svg 来操纵其
  • 计算三次贝塞尔曲线的弧长、曲线长度。为什么不工作?

    我正在用这个算法计算弧长 三次贝塞尔曲线的长度 function getArcLength path var STEPS 1000 gt precision var t 1 STEPS var aX 0 var aY 0 var bX 0
  • LeafleteachLayer函数不会迭代所有Layer

    使用 GeoJSON 数据数组创建一些标记 getJSON GetLocationsServlet function data L geoJSON data onEachFeature onEachFeature addTo mymap G
  • 使用javascript动态更新css内容

    需要将 css 更新为动态值 我不确定最好的方法是什么 div style zoom 1 div 缩放级别将根据窗口大小调整触发 应用程序将相应缩放 我将此应用程序加载到 cordova 中并让它在 iPAD 中运行 然后我意识到需要使用
  • Highcharts jQuery 渲染问题 - 所有浏览器

    我在尝试使用构建堆积柱形图时遇到了一个奇怪的问题高图表 http www highcharts com 当图表呈现时 在您调整浏览器大小之前 不会显示列无论如何 导致图表重绘 我认为 图表的其余部分显示 轴 标题等 但不显示列本身 我在 I
  • 使用 Enzyme 测试 `React.createRef` api

    我想测试下面的类 它使用React createRef api 不过 快速搜索并没有发现任何这样做的例子 有人成功过吗 我该如何嘲笑裁判 理想情况下我想使用shallow class Main extends React Component
  • 如何通过索引访问 JSON 对象中的字段

    我知道这不是最好的方法 但我别无选择 我必须通过索引访问 JSONObject 中的项目 访问对象的标准方法是只写this objectName or this objectName 我还找到了一种获取 json 对象内所有字段的方法 fo
  • 没有输入的 jQuery 日期选择器

    我有一个相当复杂的网络应用程序 我想向其中添加一些日期选择 UI 我遇到的问题是我无法从文档中弄清楚如何真正控制日期选择器的出现方式和时间 不涉及任何表单元素 不 我不会添加秘密表单字段 因此简单的开箱即用方法根本行不通 我希望有人可以提供

随机推荐

  • 小程序实现canvas绘制图片和文字并保存到手机

    HTML
  • 如何在OpenCV Python中从立体图像创建深度图?

    翻译 Shahid Akhtar Khan的 How to create a depth map from stereo images in OpenCV Python 可以使用立体 stereo 图像创建深度图 为了从立体图像构建深度图
  • 在弄清什么是真正的OKR之前,别轻易使用

    转自 https www sohu com a 167148654 114819 KR到底是什么 在使用OKR的时候也有哪些注意点 在没弄清楚这些事情 可不要轻易使用 OKR大概在2013年传入中国 开始主要是一些有硅谷背景的初创企业在推行
  • RuntimeError: DataLoader worker (pid(s) 17016, 18312) exited unexpectedly

    RuntimeError DataLoader worker pid s 17016 18312 exited unexpectedly 这个错误通常是由于DataLoader中的一个或多个worker进程crash引起的 原因可能是许多不
  • Android源码编译之 lunch命令分析及user和userdebug编译选项区别

    不同厂商在编译Android系统时 会选择不同产品和编译版本 在Android编译过程中 通过source lunch来选择 1 souuce build envsetup sh 加载命令 2 lunch 选择平台等编译选项 3 make
  • oracle下字段拆分,字段合并的一种方式

    在数据库处理中 我遇到了设计很让人蛋疼的表 此表处理一对多关系的方式是 将一个主键对应的多个值用逗号分割 然后存放在一个字段中 于是 我在表中遇到了类似这样的数据 表A id val 1 kate jam lucy tracy 2 jim
  • 【正则表达式04】匹配多个字符

    xyz xyz为普通字符 不是元字符 把xyz当做一个整体去匹配 x 匹配 0 个或者 1 个 x x 匹配 0 个或者任意多个 x 匹配0个或者任意多个字符 换行符除外 x 匹配至少 1 个 x x n 匹配n个x n是非负整数 x n
  • 如何通过没有直接关系的参数关联两个事物

    通过没有直接关系的参数关联两个事物 可以采用以下几种方法 统计分析 通过收集大量数据 使用统计方法发现两个事物之间的相关性 虽然两个事物之间可能没有直接的因果关系 但通过收集和分析大量的数据 可以发现它们之间存在间接的相关性 可视化分析 通
  • SaltStack 企业级自动化运维实战

    一 SaltStack 概述 1 SaltStack 简介 SaltStack是一个服务器基础架构集中化管理平台 具备配置管理 远程执行 监控等功能 一般可以理解为简化版的puppet和加强版的func SaltStack基于Python语
  • 我是一个线程

    第一回 初生牛犊 我是一个线程 我一出生就被编了个号 0x3704 然后被领到一个昏暗的屋子里 在这里我发现了很多和我一模一样的同伴 我身边的同伴0x6900 待的时间比较长 他带着沧桑的口气对我说 我们线程的宿命就是处理包裹 把包裹处理完
  • 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案...

    给定一个整数数组 nums 和一个整数目标值 target 要求在数组中找出两个整数 使得它们的和为目标值 并返回它们的数组下标 你可以假设每种输入只会对应一个答案 且同一个元素在答案中不能重复出现 你可以按任意顺序返回答案 例如 给定 n
  • Jenkins配置邮件发送测试报告

    我们用jenkins集成测试 Jenkins GitLab Python自动化测试持续集成 构建任务执行完成后 可以将测试结果通过邮件形式发送至相关人员 告知本次项目构建结果 一 开启邮箱SMTP服务 这里我用的是网易163邮箱 登录163
  • Unity 实现 角色的换装

    换装的三个要点 材质 网格 模型 unity中换装 即更改角色部位上的skinnedMeshRender组件的属性 更换mesh mesh 和骨骼的重新绑定 最后更换材质 一个模型 带有skinnedMeshRender组件 的子节点 和对
  • 灰灰-328-LeetCode682棒球比赛(vector、stack、atio()、substr()、c_str()、accumulate())

    你现在是棒球比赛记录员 给定一个字符串列表 每个字符串可以是以下四种类型之一 1 整数 一轮的得分 直接表示您在本轮中获得的积分数 2 一轮的得分 表示本轮获得的得分是前两轮有效 回合得分的总和 3 D 一轮的得分 表示本轮获得的得分是前一
  • SQLPro Studio for Mac(可视化数据库管理工具)

    SQLPro Studio for Mac是一款可视化数据库管理工具 为创建 MySQL MSSQL Oracle和Postgres连接提供支持的数据库管理解决方案 包括SSH隧道功能 SQLPro Studio为您提供了通过相同的用户界面
  • 华为免费虚拟服务器,免费试用虚拟服务器

    免费试用虚拟服务器 内容精选 换一换 本节操作介绍切换虚拟私有云的操作步骤 仅支持单网卡切换虚拟私有云 切换虚拟私有云会导致云服务器网络中断 切换虚拟私有云过程中 请勿操作云服务器的弹性公网IP 或对云服务器做其他操作 切换虚拟私有云后 云
  • OpenCV

    OpenCV Mat类的copyT clone 赋值的区别 1 clone 2 copyTo 3 等号 赋值 4 验证 先说一下Mat类的结构 Mat类我们可以分成两部分 头部分 矩阵数据部分 头部分 用于记录矩阵数据的大小 类型 数据指针
  • 遗传算法的概念和python实现

    遗传算法是一个非常经典的智能算法 主要用于解决优化问题 本文主要简单介绍一些原理 同时给出一个基于python实现的 用于解决实数内优化问题的模板 本文参考 原理 遗传算法入门详解 知乎 简单介绍 遗传算法就是借鉴生物学中的遗传 首先生成若
  • TCP三次握手详解

    一 什么是TCP三次握手 三次握手 Three way Handshake 是指建立一个TCP连接时 需要客户端和服务器总共发送3个包 三次握手的目的是连接服务器指定端口 建立TCP连接 并同步连接双方的序列号和确认号并交换 TCP 窗口大
  • 你不知道的JavaScript---------- 行为委托

    目录 Prototype 机制 面向委托的设计 类理论 委托理论 比较思维模型 JavaScript创建UI控件 控件创建渲染 ES5类继承形式 控件 类 类形式 委托控件对象 委托形式 更简洁的设计 更好的语法 内省 Prototype